正则表达式:匹配分隔符内的文本

时间:2015-03-03 20:21:26

标签: regex sed grep greedy

我会尽量清楚,希望这个问题对其他有同样问题的人有所帮助。

在我的file.txt中,我希望与命令匹配" grep"和" sed"只有"("和")"内的文字。例如:

This is my line and (this is the text to match!), and bla bla bla...

但有些行可能看起来像:

Another line (text to match 1;) something else, (text to match 2 )

这里的问题:
表达如
grep '(.*)' file.txtsed 's/(.*)//' <file.txt
将无效,因为.*默认为贪婪。  这意味着,它将匹配第二个例子,如下所示:
 另一行(文本匹配1;)其他内容,(文本匹配2

解决方案必须是非贪婪的匹配,然后我尝试使用非贪婪量词?

grep -E '\(.*?\)' file.txt

或使用sed

sed -r 's/\(.*\)//' <file.txt

在这种情况下,我们需要使用-E-r来使grep和sed读取扩展表达式,我们还需要在\之前使用(。 /> 但即使这个解决方案似乎也不起作用,我也不知道为什么 然后我尝试了类似的东西:

grep '(.*)[^(]*' file.txt

为了找到只有一个&#34;(要匹配的文字)&#34;并且,如果我想例如重写()内的文本,语法将是:

sed 's/(.*)\([^(]*\)/(new text)\1/'<file.txt

但是,虽然它似乎有用,但我发现'(.*)[^(]*'与旧版(.*)匹配某些行(这是一个谜......)

有更好的解决方案吗?

提前致谢

3 个答案:

答案 0 :(得分:1)

这个正则表达式应该有效:

\(([^\)]+)\)/g

正如你在这里看到的那样:

https://regex101.com/r/rR2uF3/1

答案 1 :(得分:1)

使用gnu awk非常简单:

s='Another line (text to match 1;) something else, (text to match 2 )'

awk 'BEGIN{ FPAT="\\([^)]*\\)" } {for (i=1; i<=NF; i++) print $i}' <<< "$s"
(text to match 1;)
(text to match 2 )

答案 2 :(得分:1)

您只需要:

$ cat file
Another line (text to match 1;) something else, (text to match 2 )

$ sed 's/(\([^)]*\)/(foo/' file
Another line (foo) something else, (text to match 2 )

$ sed 's/(\([^)]*\)/(foo/2' file
Another line (text to match 1;) something else, (foo)

$ sed 's/(\([^)]*\)/(foo/g' file
Another line (foo) something else, (foo)

永远不需要非贪婪量词?,并且很少有用,足以保证你的正则表达式阅读/理解的难度。它也不受所有工具的支持。在调试&#34;贪心&#34;匹配问题,请始终将.*更改为[^x]*,其中x是您感兴趣的字符串后面的任何字符,其中)情况下。