我正在编写一个bash脚本,用于分析html文件并想要获取每个单独的<tr>...</tr>
标签中的内容。所以我的命令如下:
$ tr -d \\012 < price.html | grep -oE '<tr>.*?</tr>'
但是似乎 grep
给我返回的结果是:
$ tr -d \\012 < price.html | grep -oE '<tr>.*</tr>'
如何使
.*
变成非贪婪模式?GNU Grep
,你可以使用 -P
使匹配结果变成非贪婪的:$ tr -d \\012 < price.html | grep -Po '<tr>.*?</tr>'
-P
选项启用Perl兼容正则表达式(PCRE),这在使用Basic Regular Expression (BRE)和Extended Regular Expression (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>
标签内部的嵌套标签。
非贪婪匹配不是 grep -E 支持的扩展正则表达式语法的一部分。如果您有 Perl/Python/Ruby 或其他程序,请改用 grep -P。或者可以考虑使用 pcregrep。
当然,如果您真的意味着
<tr>[^<>]*</tr>
你应该这样说;那样就可以使用普通的grep
了。
你可以(费力地)扩展正则表达式来接受嵌套标签,而不是<tr>
,但当然,最好使用适当的HTML解析器,而不是浪费大量时间重新发现为什么正则表达式不是正确的工具。
.*?
是 Perl 正则表达式。将您的 grep
更改为
grep -oP '<tr>.*?</tr>'
grep -oP '(?<=<tr>).*?(?=</tr>)'
-- 使用look-around来省略实际的标签。 - glenn jackman$ grep -Po '<tr>.*?</tr>' input
<tr>stuff</tr>
<tr>more stuff</tr>