我最近尝试使用sed从逗号和换行符分隔的枚举成员生成一堆方法。我遇到了以下似乎不直观的行为:
$ echo 'Hello,' | sed 's/\(.*\),\?/"Hi \1!"/g'
"Hi Hello,!"
在这里,我尝试通过\(.*\)
将逗号之前的所有内容捕获到一个组中,然后我允许使用,\?
的可选逗号。我希望这可以用第一个逗号之前的所有内容替换\1
,即Hello
,但由于某种原因,逗号也被包含在替换中,尽管它不在组内。为什么会这样?
答案 0 :(得分:1)
正则表达式默认执行贪婪匹配(从左到右),如果最贪婪的匹配不起作用则回溯。因此,对于\(.*\),\?
,最贪婪的匹配是将Hello,
与\(.*\)
匹配,而不是,\?
。
我不确定如何在基本正则表达式中进行非贪婪匹配(这是sed
使用的)。在Perl风格的正则表达式(sed
未使用)中,您在匹配运算符后面添加了一个问号,因此您使用(.*?),?
之类的内容。
您可以做的第二件事就是使用类似\([^,]*\),\?
的内容,但它会在它看到的第一个逗号处停止匹配。
答案 1 :(得分:1)
那是因为sed
正则表达式是贪婪的,而?
量词表示匹配前一个标记的0或1 - 在这种情况下为,
。
所以,这里引擎贪婪地匹配到最后,并且?
被?
设为可选的,它也被包含在捕获的组(.*)
中。
要获得所需的行为,请删除?
:
% echo 'Hello,' | sed 's/\(.*\),\?/"Hi \1!"/g'
"Hi Hello,!"
% echo 'Hello,' | sed 's/\(.*\),/"Hi \1!"/g'
"Hi Hello!"