0

我们得到了一个项目,我们必须接受一组具有非常具体要求的大型文本文件,大约 150-200 条规则。每个规则都可以通过、失败、不适用。通过失败可以是存在或缺少匹配的正则表达式。一些规则是多行的(即如果“X”存在,那么以下三行也应该存在并且它们应该包含1、2和3)。

虽然整个事情可以用非常难以阅读的正则表达式代码编写......并且每条规则都必须重新读取整个文件,但我想我会问社区是否还有其他选择?

我查看了 openrules、drools 等。没有一个比在列表中编写大量正则表达式并将每个正则表达式应用于文本文件更容易。

4

4 回答 4

2

我看不出有任何方法可以完全避免编写正则表达式并将它们应用于这些文本文件的行。(没有迹象表明定义配置文件数据的整体语法。根据该语法编写解析器 - 可能 - 很容易。没有机会?)

我看到你必须解决两个问题。一种是识别某些关键字(例如“主机名”),另一种是某些模式的存在与否取决于前面的一行或多行。

为了解决第一个问题,我会(使用 Java 代码)将行分成以空格分隔的标记,以便每一行都变成 List。

第二个问题可以使用规则来解决。

rule "hostname"
when
  Line( $n: number, $tok: tokens contains "hostname" )
  eval( $tok.get( $tok.indexOf( "hostname" ) + 1 ).length() > 4 ) // incomplete
then
  insert( new Correct( $n, "hostname" ) );
end

(请注意,布尔表达式必须防止 $tok 以“主机名”结尾。)为正确数据插入事实比为所有失败情况编写规则更容易。最后将有另一组规则检查所有需要的正确事实是否在工作记忆中。此外,可能需要检查重复的“主机名”定义,这可以使用正确的事实轻松完成。

让我们也看看另一个例子。

rule "interface"
when
    Line( $n1: number, $tok: tokens contains "interface" )
    Line( number == $n1 + 1, tokens not contains "disabled" )
    Line( number == $n1 + 2,
       tokens not contains "parameter" ||
       tokens contains "parameter" && $tok.indexOf( "parameter" ) < $tok.size() - 1 )
then
    insert( new Error( $n1, "interface configuration error" ) );
end

可能是 $tok.indexOf( "parameter" ) == 1 和 $tok.size() == 2 是必需的,但不知道这些要求的确切性质......在这里我也插入了一个否定结果用于在最后收集它,按行号排序等。

最后一点:我觉得这些验证要求的措辞太模糊了,除非你确信更严格的处理器能够处理糟糕的语法,或者规范实际上容忍了奇怪的措辞,例如, “没有他的戒指的主机名土星;-)”这是一个正确的行吗?它根据您的规则通过了测试...

于 2013-12-17T06:12:48.553 回答
0

另一个考虑因素是让数据源将数据作为 xml 文件发送给您,其中包含您可以验证的模式。如果它通过验证,那么您可以解析 xml 文件并将任何进一步的正则表达式规则应用于架构无法指定的标签内的数据。如果验证器不喜欢数据,它会告诉你它不喜欢哪一行(你可以得到一个现成的验证器,你不必编写自己的验证器)。这样,数据源可以确保他们的程序在将数据发送给不知道有多少客户之前生成有效数据,并且您的程序可以验证您没有接受不良数据。我知道它可能不适用于您当前的情况(必须接受文本文件而不是 xml 文件),但它对于未来的设计需要考虑。

于 2013-12-16T18:54:52.203 回答
0

如果“文本”有任何规律,你应该能够为该结构定义一个语法,然后使用经典的解析技术来检查文本是否符合结构,并使用经典的语义分析技术来验证结构化文本是否有额外的期望属性(例如,您的“有 3 行包含值 1 2 3”)。

使用语法还可以让您轻松表达正则表达式根本无法做到的约束(例如,“所有左括号都有相应的右括号”,“结构 A 包含在 C 内部的结构 B 中”,...)这就是重点“上下文无关”(语法)与“常规”语言(这是正则表达式可以识别的)。

最后,使用语法和解析器意味着您不必在文件上单独运行正则表达式。好的解析器生成器会将语法规则组合成一个高效的引擎,无论您有多少语法规则,它都会一次挑选出模式。

于 2013-12-16T18:22:05.940 回答
0

我不太清楚你告诉我们什么样的语法,但如果你认为对于一组正则表达式来说太复杂了,那么也许你应该为语法编写一个适当的解析器,例如使用优秀的ANTLR .

于 2013-12-16T17:46:43.597 回答