任何人都可以解释“sed-regex here”中发生的事情

时间:2017-07-16 12:52:58

标签: regex bash sed

我正在使用正则表达式练习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 

第一个括号是捕获前两列,第二个是最后一列,为什么第一个括号没有捕获第一列?

2 个答案:

答案 0 :(得分:8)

问题不在于你对正则表达式和贪婪匹配等的理解。问题很简单,问题中的示例用法中没有实现+

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中都有效。 只要有可能,选择适用于两者的语法都是件好事, 防止各种调试地狱。

答案 1 :(得分:3)

Casimir et Hippolyte在评论中指出,+在sed中不可用。

s/\(.*\) \(.*\) /\2 \1 /说“匹配0个或多个字符后跟一个空格,后跟0个或更多个字符,后跟一个空格。所以要匹配,输入字符串必须至少有2个空白字符,任意数量的其他字符,但必须至少有2个空格

s/\(.*\) \(.*\)/\2 \1 /说“匹配0个或多个字符后跟一个空格,后跟0个或更多字符。所以要匹配,输入字符串必须至少1个空格和任意数字其他字符。由于.*是贪婪的,它匹配第一列,第一个空格和第二列,然后模式的空格部分与输入的第二个空格匹配,最后.*评估为0个字符。