我正在使用正则表达式练习 sed 命令,但结果不如预期。我在 mac Sierra 上使用终端。 这是输入数据:
Mark watermellons 12
Robert pears 4
Terry oranges 9
Lisa peaches 7
Susy oranges 12
Mark grapes 39
Anne mangoes 7
Greg pineapples 3
Oliver rockmellons 2
Betty limes 14
我正在尝试交换第一列和第二列。我使用了这个命令:
sed 's/\(.+\) \(.+\) /\2 \1/ ' file.txt
此命令返回相同的输入。但是当我使用时,
sed 's/\(.*\) \(.*\) /\2 \1 /' file.txt
列正在交换。为什么“+”不匹配,因为每行中至少有一个字符。
此外, 当我使用
sed 's/\(.*\) \(.*\)/\2 \1 /' file.txt
第一个括号捕获前两列,第二个捕获最后一列,为什么第一个括号不捕获第一列?
最佳答案
问题不在于你对正则表达式和贪婪匹配等的理解。问题很简单,+
没有在问题中使用的示例中实现。
在 sed
中,默认情况下,+
并不像您习惯的那样表示“一个或多个前面的符号”来自其他正则表达式语法。
为了使它在 BSD sed
中工作(就像你在 OSX 上一样),
您需要使用 -E
启用扩展正则表达式,
并更改捕获组语法:
sed -E 's/(.+) (.+) /\2 \1/ ' file.txt
另请注意,+
基本上只是一个快捷方式,
所以你总是可以用老式的方式来写它:
sed 's/\(..*\) \(..*\) /\2 \1/' file.txt
顺便说一句,请始终注意 BSD sed
和 GNU sed
之间的区别。
例如,这在 GNU sed
中按预期工作,但在 BSD sed
中不工作:
sed 's/\(.\+\) \(.\+\) /\2 \1/ ' file.txt
本文中的前两个解决方案适用于 GNU 和 BSD sed
。
只要有可能,最好选择适用于两者的语法,
以防止各种调试 hell 。
关于regex - 任何人都可以解释 "sed-regex here"中发生了什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45128829/