两个标签之间的文字


23

我想<tr> </tr>从html文档中检索这两个标签之间的任何内容。现在,我没有任何特定的html要求可以保证html解析器。我只是简单地需要一些匹配的东西,<tr></tr>在两者之间获取所有内容,并且可能会有多个trs。我尝试了awk,它可以工作,但是由于某种原因,它最终给了我提取的每一行的副本。

awk '
/<TR/{p=1; s=$0}
p && /<\/TR>/{print $0 FS s; s=""; p=0}
p' htmlfile> newfile

怎么办呢?


IIUC您的awk脚本应为:'/<tr/{p=1}; p; /<\/tr>/{p=0}'。如果不起作用,请张贴一些示例输入和预期输出。
雷神

由于您awk正在工作,但要提供重复的内容,请尝试通过传递awk的输出sort -u来使其与众不同
igiannak

Answers:


14

如果您只想要...全部<tr>...</tr>

grep -o '<tr>.*</tr>' HTMLFILE | sed 's/\(<tr>\|<\/tr>\)//g' > NEWFILE

对于多行,请执行以下操作:

tr "\n" "|" < HTMLFILE | grep -o '<tr>.*</tr>' | sed 's/\(<tr>\|<\/tr>\)//g;s/|/\n/g' > NEWFILE

检查字符“ |”开头的HTMLFILE (不是通常的,但是可能的),如果存在,请更改为不存在的一种。


1
仅当开始和结束标记在同一行上时,这才起作用。
l0b0

echo "bla<tr>foo</tr>bla<tr>bar</tr>bla" | grep -o '<tr>.*</tr>' | sed 's/\(<tr>\|<\/tr>\)//g'fooblabar。该bla不应该在那里?
NN

@ l0b0正确。将使用兼容多行的...
xx4h 2013年

grep -Po '<tr>.*?</tr>'将在@NN的情况下每行返回一个结果,但是它不是可移植的。
l0b0

我不确定“ specs”或“ spec-style”是什么意思,但请注意,您的网络浏览器使用html解析器,并且html解析器将解析html,无论其编写方式如何。它不会解析非html的内容,但是您的浏览器也不会解析,因此没有人会费心编写解析器无法解析的“ html”。换句话说:绝对不错的解析器绝对是您最好的选择。
goldilocks

11

您确实需要保证HTML解析器的要求:您需要解析HTML。Perl的HTML :: TreeBuilder,Python的BeautifulSoup等易于使用,比编写复杂而脆弱的正则表达式更容易。

perl -MHTML::TreeBuilder -le '
    $html = HTML::TreeBuilder->new_from_file($ARGV[0]) or die $!;
    foreach ($html->look_down(_tag => "tr")) {
        print map {$_->as_HTML()} $_->content_list();
    }
' input.html

要么

python -c 'if True:
    import sys, BeautifulSoup
    html = BeautifulSoup.BeautifulSoup(open(sys.argv[1]).read())
    for tr in html.findAll("tr"):
        print "".join(tr.contents)
' input.html

9

sed并且awk不太适合此任务,您应该使用适当的html解析器。例如,hxselect来自w3.org:

<htmlfile hxselect -s '\n' -c 'tr'

我不知道hxselect是最好的选择。我没有使用过它,手册页确实说它“读取了格式良好的XML文档”,而许多html文档却没有。可能值得一试。可用于perl,python等的html解析器库。等 如果可以的话,会更好。
goldilocks

2
@goldilocks:最佳选择取决于情况。以我的经验hxselect,使用格式正确的html / xml文档做得很好。而且,它的使用速度比perl,python和其他工具更快。我认为/ 和解析器库hxselect之间是很好的中间立场。sedawk
2013年

1
如果有效,那就太好了!我只是向TechJack添加了一个警告,以防万一没有这样做-因为我还建议使用某种解析器;)编程的lib库当然更尴尬,但应该处理任何可远程传递的html。
goldilocks 2013年

雷神(Thor),hxselect看起来不错,一定会进一步探索它。谢谢。
TechJack

@goldilocks:hxnormalize处理格式不正确的html / xml文件。
tokland

5

如果ruby可用,您可以执行以下操作

ruby -e 'puts readlines.join[/(?<=<tr>).+(?=<\/tr>)/m].gsub(/<\/?tr>/, "")' file

file您输入的html文件在哪里。该命令执行一个Ruby单一代码行。首先,它从中读取所有行file并将它们连接到字符串readlines.join。然后,它从字符串中选择介于(但不包括)之间的任何字符,<tr>并且<\/tr>该字符是一个字符或更长,而与换行符无关[/(?<=<tr>).+(?=<\/tr>)/m]。然后,它从字符串中删除任何字符串<tr></tr>字符串gsub(/<\/?tr>/, "")(这对于处理嵌套tr标签是必需的)。最后,它输出字符串puts

您说过不应该为您使用html解析器,但是将Nokogiri与之一起使用非常容易,ruby并且使命令更简单。

ruby -rnokogiri -e 'puts Nokogiri::HTML(readlines.join).xpath("//tr").map { |e| e.content }' file

-rnokogiri加载Nokogiri。Nokogiri::HTML(readlines.join)读取的所有行filexpath("//tr")选择每个tr元素并map { |e| e.content }选择每个元素的内容,即<tr>和之间的内容</tr>


1

grep

tr跨多行检索标记中的内容,xargs请先将其传递,例如:

curl -sL https://www.iana.org/ | xargs | egrep -o "<tr>.*?</tr>"

要仅返回内部HTML,请使用:

curl -sL https://www.iana.org/ | xargs | grep -Po "<tr>\K(.*?)</tr>" | sed "s/..tr.//g"

检查perlre扩展模式的语法。

注意:为了提高性能,您可以考虑使用ripgrep哪种语法。


它无需xargs即可打印出更好的外观,使用egrep -o“ <script。*?</ script>”查找内联javascript很方便
安德鲁

0

pup

使用示例pup(使用CSS选择器):

pup -f myfile.html tr

要仅打印不带标签的文本,请使用:pup -f myfile.html tr text{}

以下是一些示例curl

curl -sL https://www.iana.org/ | pup tr text{}
pup -f <(curl -sL https://www.iana.org/) tr text{}

xpup

xpup用于HTML / XML解析(支持XPath)的示例:

xpup -f myfile.html "//tr"

0

如果只是<tr>s 的快速清单,这可能会有所帮助:

perl -ne 'print if /<tr>/../</tr>/' your.html > TRs.log

干杯

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.