我正在使用正则表达式练习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
Run Code Online (Sandbox Code Playgroud)
我正在尝试交换第一列和第二列.我使用了这个命令:
sed 's/\(.+\) \(.+\) /\2 \1/ ' file.txt
Run Code Online (Sandbox Code Playgroud)
此命令返回相同的输入.但是当我使用时,
sed 's/\(.*\) \(.*\) /\2 \1 /' file.txt
Run Code Online (Sandbox Code Playgroud)
列正在交换.为什么"+"不匹配,因为每行至少有一个字符.
另外,当我使用时
sed 's/\(.*\) \(.*\)/\2 \1 /' file.txt
Run Code Online (Sandbox Code Playgroud)
第一个括号是捕获前两列,第二个是最后一列,为什么第一个括号没有捕获第一列?
问题不在于你对正则表达式和贪婪匹配等方面的理解.问题只是在问题+中的示例使用中没有实现.
在sed,在默认情况下,+并不意味着"一个或多个前面的符号",你可能会从其他的正则表达式语法习惯了.要在BSD这项工作sed(因为你是在OSX),则需要启用与扩展正则表达式-E,也改变捕获组语法:
sed -E 's/(.+) (.+) /\2 \1/ ' file.txt
Run Code Online (Sandbox Code Playgroud)
另请注意,这+基本上只是一个快捷方式,因此您可以始终以良好的老式方式编写它:
sed 's/\(..*\) \(..*\) /\2 \1/' file.txt
Run Code Online (Sandbox Code Playgroud)
顺便说一句,总是要注意BSD sed和GNU 之间的区别sed.例如,这在GNU中可以正常工作,sed但在BSD中没有sed:
sed 's/\(.\+\) \(.\+\) /\2 \1/ ' file.txt
Run Code Online (Sandbox Code Playgroud)
这篇文章的前两个解决方案同时适用于GNU和BSD sed.只要有可能,最好选择适用于两者的语法,以防止各种调试地狱.