如何使用sed从字符串中提取文本?


95

我的示例字符串如下:

This is 02G05 a test string 20-Jul-2012

现在我要从上面的字符串中提取02G05。为此,我用sed尝试了以下正则表达式

$ echo "This is 02G05 a test string 20-Jul-2012" | sed -n '/\d+G\d+/p'

但是上面的命令什么都不打印,我相信这是因为它无法与我提供给sed的模式相匹配。

所以,我的问题是我在这里做错了什么以及如何纠正它。

当我使用python尝试上述字符串和模式时,得到了我的结果

>>> re.findall(r'\d+G\d+',st)
['02G05']
>>>

6
Python绝对不是sed。他们的正则表达式味道截然不同。
Tripleee 2013年

Answers:


91

您的\d可能不支持该模式sed。尝试[0-9][[:digit:]]代替。

要仅打印实际匹配项(而不是整个匹配行),请使用替换。

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

6
谢谢,它工作正常。但是我有一个问题,为什么.*您的正则表达式是必要的,因为当我尝试sed -n 's/\([0-9]\+G[0-9]\+\)/\1/p'它时,它只会打印整行。
RanRag

7
那就是为什么,不是吗?用norhing替换比赛前后的所有内容,然后打印整行。
Tripleee'7

1
@tripleee这只会打印2G05不出来02G05。有效的表达方式是's/.*\([0-9][0-9]G[0-9][0-9]*\).*/\1/p'
Kshitiz Sharma

1
这会将它硬编码为两位数。这样的事情sed -n 's/\(.*[^0-9]\)\?\([0-9][0-9]*G[0-9][0-9]*\).*/\2/p'会更普遍。(我假设您sed支持\?零到一
件事

又见stackoverflow.com/a/48898886/874188如何更换其他各种常见的Perl逃脱像\w\s等等
tripleee

99

使用grep -E怎么样?

echo "This is 02G05 a test string 20-Jul-2012" | grep -Eo '[0-9]+G[0-9]+'

3
+1这比较简单,也可以正确处理同一行上多次匹配的情况。sed可以为这种情况设计一个复杂的脚本,但是为什么要麻烦呢?
2012年

egrep使用扩展的regexp,sedgrep使用标准的regexp, egrepgrep -esed -E使用扩展的regexp,并在问题的Python代码使用PCRE,(perl的常见的正则表达式)GNU的grep可以使用PCRE与-P选项。
Felipe Buccioni,2016年

@FelipeBuccioni实际上这应该是egrepgrep -Esed -r
SensorSmith

对于单个(第一个)匹配项,请附加`| 头-1`(不含反引号),按这样的回答另一个问题。
SensorSmith

1
grep-m 1后的首场比赛停止。
Tripleee '18


5

尝试以下方法:

echo "This is 02G05 a test string 20-Jul-2012" | sed 's/.* \([0-9]\+G[0-9]\+\) .*/\1/'

但是请注意,如果一行上有两个图案,它将打印第二个图案。


如果有多个匹配项,则通常是最后一个。
Tripleee'7

0

尝试使用rextract。它使您可以使用正则表达式提取文本并将其重新格式化。

例:

$ echo "This is 02G05 a test string 20-Jul-2012" | ./rextract '([\d]+G[\d]+)' '${1}'

2G05

如果使用标准正则表达式,则方括号\d完全是多余的。
人间
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.