【发布时间】:2012-08-19 11:56:47
【问题描述】:
如果这是在某个地方发布的,我深表歉意,但我粗略的搜索没有找到任何东西。
在进行一些 Python 编程时,我注意到以下命令:
re.sub("a*((ab)*)b", r"\1", "aabb")
返回空字符串。但是 sed 中的等效命令:
echo "aabb" | sed "s/a*\(\(ab\)*\)b/\1/"
返回ab。
对我来说,python 正则表达式开头的“a*”指令将匹配两个a,导致“(ab)*”匹配零次,但我不知道如何 sed提出ab。有谁知道导致这种情况的两个正则表达式引擎之间有什么区别?我相信默认情况下它们都贪婪地匹配星星,但我想到 sed 可能从右边而不是左边匹配。任何见解将不胜感激。
【问题讨论】:
-
某处我读到“sed/awk 使用 DFA”和“python/perl/java 使用 NFA”。它确实通过交替(回溯?)改变语义......这可能相关吗?
-
@pst:也许我误解了你,但似乎任何基于回溯的方法都会使用 DFA;使用 NFA 的效果是消除回溯的需要,因为同时检查所有分支。所以,我期待 Perl/Python/Java/等。使用 DFA。有没有可能你读到的与你写的相反:也许你读到 sed/awk 使用 NFA 而 Perl/Python/Java 等使用 DFA?
-
@pst:如果 sed/awk 使用 NFA,它会解释观察到的行为,然后选择匹配最长的匹配方式。在这种情况下,让
\(\(ab\)*\)匹配ab会产生更长的整体匹配aabb,然后让它匹配空字符串,因为后者意味着整个正则表达式将只匹配aab。跨度> -
@pst:对我之前的 cmets 的更正:foo.be/docs/tpj/issues/vol1_2/tpj0102-0006.html 使用术语“NFA”来描述执行回溯的正则表达式引擎,而使用“DFA”来描述不执行回溯的正则表达式引擎。现在我想起来了,我想这是有道理的;一个“NFA”引擎给自己做一个注释“我在这里做了一个不确定的决定,所以如果我回溯到这一点,我应该尝试一个不同的分支”,而一个“DFA”引擎将 NFA 预先转换为非- 通过爆炸状态数回溯 DFA。但是该页面还声称 sed 和 Perl 都使用 NFA 引擎。 :-/
-
不,sed RE 是贪婪的。它只是遵循 POSIX 并在找到一个匹配项后不会停止。