2

假设我们有两个正则表达式:

1234.*

.*

输入:

1234567

显然它们都匹配,但 1234.* 匹配更好,因为它更具体。即更相关。有没有标准的方法来检查哪个更相关?

编辑:

一些澄清。我想通过检查哪个正则表达式与输入最匹配来做出决定。在这种情况下,我只匹配数字。

电话号码示例:

输入:

31882481337

我们对以下每个正则表达式都有一个规则:

31.*
.*

在这种情况下,我希望使用绑定到 31.* 的规则,因为这对于给定的输入更具体。如果我不使用正则表达式会很容易,因为我可以使用评分机制来检查它的匹配程度,但是这些规则可能有一些更高级的正则表达式,例如:

31[89].*
4

4 回答 4

4

我认为没有简单的方法可以做到这一点。如果您查看更复杂的示例,您很快就会意识到要准确定义“更相关”是相当困难的。断言和反向引用之类的所有东西都会发挥作用。

我可以想到两种方法来粗略估计“相关性”。

  1. 随机修改输入并比较有多少修改导致每个表达式失败。

  2. 分析表达式本身。计算并比较终端符号与通配符的数量,断言的数量以及您喜欢的任何内容。

特别是在第二个解决方案中,您必须意识到实际匹配未使用的许多替代方案可能会使结果变得无关紧要。

h.*|verylongtext|anotherverylongtext

hell.*|v.*

匹配“hello”时,第二个表达式“更相关”,但第一个表达式包含更多的终端符号,并且可能通过第二个解决方案获得更好的排名。但是对于匹配“verylongtext”,第一个是“更相关”。这表明“相关性”在很大程度上取决于实际输入,您必须分析实际的匹配路径——这是第一个解决方案隐含地完成的。但是随机修改输入是一项相当艰巨的任务,因为可能输入的空间非常大。我认为这也不会很好地工作。

于 2009-07-14T20:51:17.950 回答
1

我能想到的一个因素是一种语言是无限的还是不是无限的。不是无限的肯定比无限更相关,因为语言中可接受的单词数量是有限的。

如果像你的例子一样测量无限的语言,两者都会永远持续下去,你可以继续计算语言中的每个单词,直到你脸色发青,你永远不会得出结论。

直到您认为第一个正则表达式的语言是第二个语言的适当子集。那么你可能会说一个更相关。

我不确定如何衡量正则表达式相关性的任何标准。

为了阐述适当子集的概念,您可能会问您的语言是什么,您的正则表达式是否接受除此之外的单词?您的表达可能仍然有效,但它包含的单词范围比您预期的要广泛......当然,如果您的输入受到控制,这可能无关紧要,但这是您衡量相关性的一种方式。它完全接受我的语言吗?

你的就是一个很好的例子,也许你想接受以 1234 开头的数字。1234.*就像一个魅力......但这不是你指定的语言。`1234\d* 更具体,并且与您指定的语言完全匹配......因此更相关。

但这都是从纯理论的角度来看的,并且可能不会帮助您以编程方式确定一个正则表达式是否比另一个更好。

于 2009-07-14T20:50:27.733 回答
1

Has been a long time since I asked this question, but I wanted to let you know what I came up with in the end. I went for a far simpler approach, I just added a weight factor to my regular expressions. So you could say I defined the relevance of the regular expression myself instead of trying to define it using regular expressions:

Expression      Relevance
31.*              1
.*              0
于 2010-12-14T12:55:14.873 回答
0

我不知道“相关性”是否是真正的问题。每个都是相关的,并且每个都将按照您的建议匹配“1234567”。但是,正如您所说,一个 ("1234.*") 更具体。使用正则表达式,特异性非常好(在这样的简单情况下),有时您可以深入研究它,直到您意识到您根本不需要一个(正则表达式)。正则表达式规则#1:如果不需要,不要使用它们。例如,要匹配“1234567”,我会选择:

$source = '1234567';
if ( stripos( $source, '1234' ) === 0 ) {
  $foo = substr( $source, 4 );
  // $source began with '1234' and $foo holds the rest
} else {
  // it didn't begin with '1234'
}

That's a PHP example, but the idea is that, since you've honed your accepted value in so tightly, you don't even need PCRE anymore. "Relevancy" won't really tell you much about a regular expression (how would you define "relevancy" in this context?), however I think specificity a more objective measurement, and being able to use non-regex string functions instead would sure as heck be very measurably specific (in fact, it's boolean - are there regular expression or not?).

Outside of being able to reduce the regex out of the equation: To measure the specificity of a given regular expression, simply compare (heuristically, if necessary) how many different values would satisfy the expression. The expression with the least score in this test would prove the most specific.

于 2009-07-14T21:18:07.847 回答