【发布时间】:2012-10-05 00:47:13
【问题描述】:
我有一个正则表达式,其中相同的匹配条件可以应用于多个分隔符。 []、() 和 <> 均有效。例如,它看起来像这样:
\[.\]|\(.\)|<.>
有没有办法从上面的正则表达式中删除冗余?分隔符内的匹配条件始终相同,但分隔符本身可能不同。
【问题讨论】:
我有一个正则表达式,其中相同的匹配条件可以应用于多个分隔符。 []、() 和 <> 均有效。例如,它看起来像这样:
\[.\]|\(.\)|<.>
有没有办法从上面的正则表达式中删除冗余?分隔符内的匹配条件始终相同,但分隔符本身可能不同。
【问题讨论】:
我猜你问是因为
[[(<].[])>]
不够准确,原因很明显。
回答“不,没有办法”总是很危险的,因为很难确定一个人已经检查了所有可能的方法。在这种情况下,人们必须经常拿出可靠的证据来回答。
我不确定这是一个足够强大的证明,甚至根本不是“证明”,但考虑一下这个(伪)信息论观点:
PCRE 引擎本身不知道字符对[]、() 和<> 之间的任何关系。因此,表达式本身必须包含该信息,即要求至少有六个字符[]()<>。
不仅如此,出于同样的原因,表达式本身必须至少定义两个配对(隐含第三个)。我不确定如何证明两个交替运算符 (|) 是你能做的最好的,但我的意思是,即使有 更紧凑的方法,你也会保存最多一个字符,因为至少需要一位来表示“配对存在!”
元字符的转义只能通过 []() 可以出现在字符类中而不被转义的事实来压缩,但首先,这并不是真正的“消除冗余”是“语法上的幸运情况”,其次,您仍然需要为所述字符类的定义添加两个字符:[]。
因此,我相信即使从理论角度来看,如果我对正则表达式引擎无法知道的假设是正确的,那么最多可以保存 em> 您已经提供的正则表达式中的三个字符:\[.\]|\(.\)|<.>。
我热切期待正则表达式大师的纠正!
【讨论】:
如果你真的在使用PCRE library(例如通过 PHP),你可以使用 DEFINE 组来创建一个子例程,如下所示:
'~(?(DEFINE)(?<content>\w+))(?:<(?&content)>|\[(?&content)\]|\((?&content)\))~'
...或更易读:
(?(DEFINE)(?<content>\w+))
(?:
<(?&content)>
|
\[(?&content)\]
|
\((?&content)\)
)
这是 PHP 中的 demo。它也应该在 Perl 中工作。
【讨论】: