看来我正坐在我的眼睛上,因为我无法找出我的正则表达式有什么问题:
我正在尝试解析一个在一行中包含字符串的 C 源文件(实际上这些字符串是正则表达式,但这并不重要)。 基本上
/"([^"]*)"/
应该捕获字符串(不带引号),除非其中有双引号。
我也可以使用
/(\\"*)/!
匹配字符串中的双引号,但我未能组合两个正则表达式:
使用
/"((?:[^"]|\\")*)"/
(捕获双引号之间的文本,直到第一个非转义双引号)捕获在第一个 "
之后结束,如本示例调试器会话所示:
DB<15> $x='"SAMSUNG SSD SM841N? (2\\.5\"? 7mm |mSATA )?(128|256|512)GB( SED)?|"'
DB<16> x $x =~ s/"((?:[^"]|\\")*)"//
0 1
DB<17> x $x
0 '? 7mm |mSATA )?(128|256|512)GB( SED)?|"'
DB<18>
在写这个问题时,我尝试交换两种选择,突然它起作用了:
DB<18> $x='"SAMSUNG SSD SM841N? (2\\.5\"? 7mm |mSATA )?(128|256|512)GB( SED)?|"'
DB<19> x $x =~ s/"((?:\\"|[^"])*)"//
0 1
DB<20> x $x
0 ''
DB<21>
那么正则表达式
A|B
和B|A
不是等价的吗?
当我在写问题时找到答案时,我本可以取消提问,但因为我认为这对其他人来说也可能很有趣,所以我将在这里提供我的答案:
来自 man perlre(1):
从左到右尝试替代方案,因此找到的第一个与整个表达式匹配的替代方案就是被选择的方案。这意味着替代方案不一定是贪婪的。例如:当将“foo|foot”与“barefoot”匹配时,只有“foo”部分会匹配,因为这是尝试的第一个替代方案,并且它成功匹配目标字符串。 (这可能看起来并不重要,但是当您使用括号捕获匹配的文本时,它很重要。)
所以实际上是的,替代品的顺序很重要。