非贪心匹配使用?用grep

时间:2013-10-01 20:21:02

标签: regex bash grep

我正在编写一个分析html文件的bash脚本 我想获得每个<tr>...</tr>的内容。所以我的命令如下:

$ tr -d \\012 < price.html | grep -oE '<tr>.*?</tr>'

但似乎grep给了我结果:

$ tr -d \\012 < price.html | grep -oE '<tr>.*</tr>'

如何让.*非贪婪?

4 个答案:

答案 0 :(得分:14)

如果您有GNU Grep,则可以使用-P使比赛变得非贪婪:

$ tr -d \\012 < price.html | grep -Po '<tr>.*?</tr>'

-P选项启用Perl Compliant正则表达式(PCRE),这是与?非贪婪匹配所需的基本正则表达式(BRE)< / em>和扩展正则表达式(ERE)不支持它。

如果您使用-P,还可以使用look arounds来避免在匹配中打印代码,如下所示:

$ tr -d \\012 < price.html | grep -Po '(?<=<tr>).*?(?=</tr>)'

如果您没有GNU grep并且HTML格式正确,您可以这样做:

$ tr -d \\012 < price.html | grep -o '<tr>[^<]*</tr>'

注意:上述示例不适用于<tr>中的嵌套代码。

答案 1 :(得分:4)

非贪婪匹配不是grep -E支持的扩展正则表达式语法的一部分。如果你有,请使用grep -P,或者切换到Perl / Python / Ruby /你有什么。 (哦,还有pcregrep。)

当然,如果你的意思是

<tr>[^<>]*</tr>

你应该这样说;然后普通的grep可以正常工作。

你可以(繁琐地)扩展正则表达式以接受不是<tr>的嵌套标签但是当然,使用正确的HTML解析器比花费大量时间重新发现为什么正则表达式不是正确的工具更好对此。

答案 2 :(得分:3)

.*?是一个Perl正则表达式。将您的grep更改为

grep -oP '<tr>.*?</tr>'

答案 3 :(得分:3)

尝试使用perl-style-regexp

$ grep -Po '<tr>.*?</tr>' input
<tr>stuff</tr>
<tr>more stuff</tr>