替换第n个正则表达式问题

时间:2017-08-14 15:14:18

标签: sed

如果我想从字符串中删除第一个句点及其后面的所有内容,请sed做:

echo 2.6.0.3-8 | sed 's/\..*//'

输出:

2

但如果我想删除第二个时期及其背后的一切,我想我应该能够这样做(GNU sed):

echo 2.6.0.3-8 | sed 's/\..*//2g'

然而输出是:

2.6.0.3-8   

从手册:

  

' NUMBER'        仅替换REGEXP的第NUMBER个匹配。

我在这里错过了什么?

3 个答案:

答案 0 :(得分:2)

这是因为表达是贪婪的。第一场比赛消耗.6.0.3-8,第二场比赛没有留下任何文字。

你的正则表达式必须更准确

$ sed -E 's/([^.]+(\.[^.]+){3}).*/\1/' <<<"2.6.0.3-8"
2.6.0.3-8
$ sed -E 's/([^.]+(\.[^.]+){2}).*/\1/' <<<"2.6.0.3-8"
2.6.0
$ sed -E 's/([^.]+(\.[^.]+){1}).*/\1/' <<<"2.6.0.3-8"
2.6
$ sed -E 's/([^.]+(\.[^.]+){0}).*/\1/' <<<"2.6.0.3-8"
2

答案 1 :(得分:2)

你在那里但被.*焚烧和贪婪。您需要针对特定​​情况执行的操作是将.*替换为[^.]*

$ echo 2.6.0.3-8 | sed 's/\.[^.]*//2g'
2.6
$ echo 2.6.0.3-8 | sed 's/\.[^.]*//3g'
2.6.0
$ echo 2.6.0.3-8 | sed 's/\.[^.]*//1g'
2

[^.]表示所有不属于点的字符。

答案 2 :(得分:1)

正如@stevesliva和@glennjackman所指出的,这里的问题是正则表达式匹配整行,因此 没有第二个匹配。

似乎没有通用的方法来实现仅使用正则表达式的替换。因此,删除第二个句点及其背后的所有内容的通用替代方法是使用Pd,例如:

echo 2.6.0.3-8 | sed 's/\./\n/2; P; d'

或便携式:

echo 2.6.0.3-8 | sed -e $'s/\\./\\\n/2' -e P -e d

两种情况下的输出:

2.6