3

我有一个正则表达式,其中相同的匹配条件可以应用于多个分隔符。 [], (), 和<>都是有效的。例如,它看起来像这样:

\[.\]|\(.\)|<.>

有没有办法从上面的正则表达式中删除冗余?分隔符内的匹配标准始终相同,但分隔符本身可能不同。

4

2 回答 2

1

如果您确实在使用PCRE 库(例如通过 PHP),您可以使用 DEFINE 组来创建子例程,如下所示:

'~(?(DEFINE)(?<content>\w+))(?:<(?&content)>|\[(?&content)\]|\((?&content)\))~'

...或者更具可读性:

(?(DEFINE)(?<content>\w+))
(?:
  <(?&content)>
  |
  \[(?&content)\]
  |
  \((?&content)\)
)

这是一个PHP演示。它也应该在 Perl 中工作。

于 2012-10-05T04:39:55.863 回答
1

我猜你问是因为

[[(<].[])>]

不够准确,原因很明显。

回答“不,没有办法”总是很危险的,因为很难确定一个人已经检查了所有可能的方法。在这种情况下,人们必须经常拿出一个可靠的证据来回答。

我不确定这是一个足够强大的证明,甚至根本不是一个“证明”,但考虑一下这个(伪)信息论观点:

  1. PCRE 引擎本身不知道字符对、 、 和 之间的[]任何()关系<>。因此,表达式本身必须包含该信息,至少需要六个字符[]()<>

  2. 不仅如此,出于同样的原因,表达式本身必须定义至少两个配对(隐含第三个)。我不确定如何证明两个交替运算符 ( |) 是你能做的最好的,但我的意思是,即使有紧凑的方法,你最多只能保存一个字符,因为至少有一个需要说,“配对存在!”

  3. 元字符的转义只能通过[]()可以出现在字符类中而不被转义的事实来压缩,但首先,这并不是真正的“消除冗余”,而是“语法中的幸运情况”,其次,您仍然需要为所述字符类的定义添加两个字符:[].

  4. 因此,我相信即使从理论的角度来看,如果我对正则表达式引擎无法知道的假设是正确的,那么一个人最多可以从您已经提供的正则表达式中保存三个字符:\[.\]|\(.\)|<.>.

我热切期待正则表达式大师的纠正!

于 2012-10-05T02:57:43.473 回答