sed 的贪婪匹配不应匹配该字符串,但确实如此

sed 的贪婪匹配不应匹配该字符串,但确实如此

根据我在网上阅读的内容,很难理解sed.我对看似懒惰的匹配感到困惑。

在 中~/tmp/tmp.txt,我有一行包含 3 个字母数字字符串,并用 2 个制表符分隔:TheQuick<TAB>BrownFox<TAB>JumpedOver。如果我发出sed -n -E '/^.+\t.+\t.+$/p' ~/tmp/tmp.txt,该行就会打印出来。

在我看来,它不应该,因为即使正则表达式匹配由 2 个制表符分隔的 3 个字符串,这些字符串也不是字母数字。因此,第一个字符串应该贪婪地吞噬该行上的所有字符,不留下任何与第一个选项卡匹配的内容。

我如何理解这种行为,以便我可以制作可靠的正则表达式?我正在使用 GNU sed

答案1

贪婪匹配系统只是意味着它会尝试找到最大的匹配字符串(意思是第一的最大,它将在整个正则表达式的第一个匹配处停止搜索),而不是即使存在匹配字符串,它也会在不匹配的字符串处停止。将其视为“为我找到最大可能的匹配项,但一定要为我找到匹配项!”的命令。由于允许第一个.\+吃掉整个字符串意味着正则表达式不匹配,因此引擎将返回并尝试其他操作。

在您的情况下,它甚至更简单,因为您将正则表达式锚定到行的开头和结尾(^$),因此.+永远无法到达行尾,因为正则表达式中还有其他内容。

这是一个可能有助于解释贪婪匹配的示例:

$ echo aaaaaaa | sed 's/a*/B/'
B

这里,由于正则表达式的a*意思是“匹配0个或多个连续a字符”,所以贪心匹配会找到最大可能的匹配细绳。非贪婪匹配(例如使用 PCRE)将返回:

$ echo aaaaaaa | perl -pe 's/a*?/B/'
Baaaaaaa

这是因为非贪婪会找到最短的匹配字符串而不是最长的。

我不明白你为什么提到字母数字或它有何相关性。也许您误解了.并认为只匹配字母数字字符串,但事实并非如此;.将匹配所有内容(取决于您使用的正则表达式的风格以及您提供的选项,它甚至可以匹配换行符)。如果您想要字母数字字符串,您可以使用[[:alnum:]]匹配 的POSIX 字符类[a-zA-Z0-9]

相关内容