regex - 任何人都可以解释 "sed-regex here"中发生了什么

标签 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 

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

最佳答案

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

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/

相关文章:

regex - perl 在 bash 中查找两个模式之间的模式

bash - ffmpeg - 超线程导致 "Conversion failed"具有多个并行实例

awk - 对没有标题和第一列的csv文件中的行进行排序

sed - 从 TNS 条目中提取主机名

regex - 从两个特定字符串之间的任何位置删除特定字符?

javascript - 附加YouTube嵌入式视频标题

regex - 如何在 bash 中删除从开始到某个特定选定单词的文本?

linux - 如何在 sed 的输出中使用变量?

linux - 尝试将序列号读入变量以与序列号列表进行比较以重命名机器

Linux:将输出变成一行