sed:仅打印匹配组


133

我想获取最后两个数字(一个整数,一个浮点数;后跟可选的空格)并仅打印它们。

例:

foo bar <foo> bla 1 2 3.4

应打印:

2 3.4

到目前为止,我有以下内容:

sed -n  's/\([0-9][0-9]*[\ \t][0-9.]*[\ \t]*$\)/replacement/p' 

会给我

foo bar <foo> bla 1 replacement

但是,如果我尝试将其替换为组1,则会打印整行。

sed -n  's/\([0-9][0-9]*[\ \t][0-9.]*[\ \t]*$\)/\1/p' 

如何仅打印与组中正则表达式匹配的行部分?

Answers:


138

匹配整行,因此.*在正则表达式的开头添加一个。这导致整个行被组的内容替换

echo "foo bar <foo> bla 1 2 3.4" |
 sed -n  's/.*\([0-9][0-9]*[\ \t][0-9.]*[ \t]*$\)/\1/p'
2 3.4

38
我必须添加-r-regexp-extended选项,否则我会收到invalid reference \1 on s命令的RHS错误。
Daniel Sokolowski

15
@DanielSokolowski我认为如果使用()而不是\(和,则会出现该错误\)
Daniel Darabos

3
.*如果您要提取的字符串并不总是在行尾,也请记住将其添加到regexp的末尾。
Teemu Leisti

3
这对我不起作用,因为.*贪婪和sed没有贪婪.*?
sondra.kinsey,

@DanielDarabos只需提及,(并且)不会在ubuntu 16.04中引发错误。所以我认为这个评论已经过时了。
李浩南

72

grep是正确的提取工具。

使用您的示例和正则表达式:

kent$  echo 'foo bar <foo> bla 1 2 3.4'|grep -o '[0-9][0-9]*[\ \t][0-9.]*[\ \t]*$'
2 3.4

12
对整个团队
都很有用

grep -o不能在运行msysgit的系统上移植,但sed可以。
cchamberlain

请参阅@jozxyqk链接的问题,以获取使用grep解决方案使用前瞻性和后视性的答案。
Joachim Breitner

您可以通过管道grep -o调用从模式中提取组。stackoverflow.com/a/58314379/117471
Bruno Bronosky '19年

12

对于另一种选择,我会选择awk!

echo "foo bar <foo> bla 1 2 3.4" | awk '{ print $(NF-1), $NF; }'

这将在空格上分割输入(我在这里使用STDIN,但您的输入很可能是一个文件),然后打印出最后一个但最后一个字段。该$NF变量保持在爆炸后的空间找到的字段数。

这样做的好处是,只要更改后两个字段之前的内容,只要您只希望后两个字段继续工作,就没有关系。


3

cut命令是为这种确切情况而设计的。它将在任何定界符上“剪切”,然后您可以指定应输出的块。

例如: echo "foo bar <foo> bla 1 2 3.4" | cut -d " " -f 6-7

将导致输出: 2 3.4

-d设置分隔符

-f选择要输出的“字段”的范围,在这种情况下,它是原始字符串的第6至第7个块。您也可以将范围指定为列表,例如6,7


要仅打印某些列,请通过管道连接至awk '{ print $2" "$6 }'
nurettin

@nurettin我想您的评论可能是针对awk答案之一的。
carlin.scott

当我访问此页面时,我尝试了cut并意识到它的局限性,因此决定在awk中编写一个更通用的版本,以作为提高此文章质量的评论。
nurettin

1
是的,我认为这与涉及awk的答案不同。执行您所写内容的cut命令是:cut -d " " -f 2,6
carlin.scott

啊,我不知道,我以为你只能给范围。感谢那。
nurettin

2

我同意@kent的说法,它非常适合grep -o。如果需要在模式中提取组,则可以使用第二个grep来完成。

# To extract \1 from /xx([0-9]+)yy/
$ echo "aa678bb xx123yy xx4yy aa42 aa9bb" | grep -Eo 'xx[0-9]+yy' | grep -Eo '[0-9]+'
123
4

# To extract \1 from /a([0-9]+)b/
$ echo "aa678bb xx123yy xx4yy aa42 aa9bb" | grep -Eo 'a[0-9]+b' | grep -Eo '[0-9]+'
678
9
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.