Jape电话号码检测规则在Annie(appelt/brill模式)无限运行求助
解决Jape规则在Appelt/Brill模式下无限运行的问题
问题根源
你的规则在Appelt或Brill控制模式下无限循环,核心原因有两个:
- 无效匹配的重复触发:Appelt/Brill是增量匹配模式,规则会在每次执行后重新扫描文档。你的第二个分支全由可选节点(
?)组成,可能匹配空序列、单个标点或短数字——这些序列在动作里会被过滤(因为偏移量不足10),但规则不会产生任何标注,导致控制逻辑认为需要反复执行规则来寻找匹配。 - 模糊的匹配范围:松散的可选节点组合让规则可以匹配大量不满足最终条件的短序列,每次匹配后没有"消耗"足够的标注或Token,触发无限迭代。
解决方案
通过收紧规则的匹配约束,提前过滤掉无效序列,避免无意义的重复匹配:
- 移除空匹配可能,确保每个分支至少匹配足够的数字字符
- 提前在规则模式里约束数字总位数,而非等到动作里才过滤
- 优化分支结构,减少重叠匹配的可能性
修改后的Jape规则
Phase: PhoneFinder Input: Token Options: control = appelt debug = false Rule: PhoneRule ( // 分支1:10位连续数字 {Token.kind == number, Token.category == CD, Token.length == 10} | // 分支2:带括号/短横线的标准格式(比如(123)456-7890) ( ({Token.kind == punctuation, Token.category == "("})? {Token.kind == number, Token.category == CD, Token.length >= 3, Token.length <=4} ({Token.kind == punctuation, Token.category == ")"} )? ({Token.kind == punctuation, Token.category == "-"} )? {Token.kind == number, Token.category == CD, Token.length >= 7} ) | // 分支3:带冒号分隔的格式(比如123:456:7890),确保总数字位数≥10 ( {Token.kind == number, Token.category == CD}+ ({Token.kind == punctuation, Token.category == ":"} {Token.kind == number, Token.category == CD}+)+ ) ) :phoneLookup --> { AnnotationSet rawPhone = bindings.get("phoneLookup"); if(rawPhone == null || rawPhone.size() == 0) return; // 统计总数字位数,替代偏移量判断(更准确) int digitCount = 0; for (Annotation token : rawPhone) { if (token.getFeatures().get("kind").equals("number")) { digitCount += ((String)token.getFeatures().get("string")).length(); } } if (digitCount >= 10) { FeatureMap features = Factory.newFeatureMap(); features.put("rule","PhoneRule"); features.put("kind","phone"); outputAS.add(rawPhone.firstNode(), rawPhone.lastNode(), "PhoneFinder", features); } }
关键改动说明
- 第二个分支不再允许数字节点可选,强制要求区号部分3-4位、主体部分至少7位,确保匹配序列本身符合电话号码结构
- 第三个分支重构为
数字+(:数字)+的结构,避免空匹配,同时保证总数字位数足够 - 动作里用数字位数统计替代偏移量判断,更准确(偏移量可能包含标点长度),同时提前返回空匹配的情况
- 移除了原规则中可能匹配空序列的松散结构,从根源上避免无效匹配触发的循环
内容的提问来源于stack exchange,提问作者Mehtab Singh
相关产品推荐
相关产品推荐

