我想使用sed命令来获得更好的性能:
sed -n '/<html>/,/<\/html>/p' filename > output
此命令效果很好。 但是我在一个文件中有多个html标签。 我想在第一次出现的HTML标签之间提取内容 ,
答案 0 :(得分:2)
这应该会给你第一个<html>
阻止。
sed -n '/<html>/,/<\/html>/p;/<\/html>/q' file
示例:
kent$ cat file
<html>
a
</html>
<html>
b
</html>
<html>
c
</html>
kent$ sed -n '/<html>/,/<\/html>/p;/<\/html>/q' file
<html>
a
</html>
顺便说一句,我不认为OP正在解析html / xml。 html没有多个<html>
标记。他的输入文件也可能不在xml中。
答案 1 :(得分:1)
因此,假设您要在&lt; html&gt;之间提取内容。 ..&lt; / html&gt;分隔符,但您的文本文件中有多组分隔符。例如;
blah <html> this </html> blah <html> that </html> blah
blah
<html>
the_other </html>
应该返回
this that the_other
(注:
如果只有一对&lt; html&gt;,那么原始海报给出的sed脚本可以正常工作。 ..&lt; / html&gt;分隔符。问题是同一文件中有多个副本。
顺便说一句,这不是“解析HTML”。使用正则表达式的问题在于,真正的正则表达式无法与嵌套标记匹配,并且您无法嵌套&lt; html&gt;标记)。
这是我对它的攻击(使用perl):
perl -e '$/=""; $_=<>; while (m#\G(.*?)<html>(.*?)</html>#gs) {print "<html>$2</html>\n";}' filename > output
我相信这可以做你想要的。
(说明:
perl -e 'command'
运行perl脚本command
。$/=""
清除记录分隔符,因此Perl将整个文件视为一个“行”。$_=<>
将整个文件读入变量$_
。while ($condition) {print "$stuff";}
不言自明。m#$pattern#gs
全局匹配$ pattern(g
); s
允许.
匹配任何字符,包括\n
。如果您通过m
为匹配添加前缀,则可以使用任何分隔符而不是/
;我使用了#
。\G(.*?)<html>(.*?)</html>
中,\G
表示最近全局匹配的位置,两个.*?
匹配任意字符串(?
匹配非贪婪,所以我们采取最短的比赛而不是最长的比赛,并且...... ( )
捕获我们在变量$1
和$2
中使用的字符串,因此我们可以在<html>
... {{1}之间复制字符串在我们的print语句中作为</html>
。)答案 2 :(得分:0)
将您的文件视为文本文件。如果需要解析HTML,则必须使用一些HTML解析器。
请注意,只有当您的内容标记为一行时,此代码才有效。
如果您只需要获取第一个标记的值,此行可以提供帮助。
sed -n "/<html>/,/<\\/html>/{/>.*<\//{s/^[^>]*>\\([^<]*\\)<\\/.*/\1/gp;q}}" file.html
测试文件file.html
:
<html>
<body>
<ccc>test1</ccc><bbb>test2</bbb>
<ccc1>test3</ccc1><bbb1>test4</bbb1>
</body>
</html>
试验:
$ sed -n "/<html>/,/<\\/html>/{/>.*<\//{s/^[^>]*>\\([^<]*\\)<\\/.*/\1/gp;q}}" file.html
test1
按标签名称获取价值:
sed -n "/<html>/,/<\/html>/{/<$tag>/,/<\\$tag>/{s/.*$tag>\\([^<]*\\)<\\/$tag.*/\1/gp;q}}" file.html
试验:
$ tag=ccc
$ sed -n "/<html>/,/<\/html>/{/<$tag>/,/<\\$tag>/{s/.*$tag>\\([^<]*\\)<\\/$tag.*/\1/gp;q}}" 11
test1
$ tag=bbb
$ sed -n "/<html>/,/<\/html>/{/<$tag>/,/<\\$tag>/{s/.*$tag>\\([^<]*\\)<\\/$tag.*/\1/gp;q}}" 11
test2
$ tag=ccc1
$ sed -n "/<html>/,/<\/html>/{/<$tag>/,/<\\$tag>/{s/.*$tag>\\([^<]*\\)<\\/$tag.*/\1/gp;q}}" 11
test3
$ tag=bbb1
$ sed -n "/<html>/,/<\/html>/{/<$tag>/,/<\\$tag>/{s/.*$tag>\\([^<]*\\)<\\/$tag.*/\1/gp;q}}" 11
test4
答案 3 :(得分:0)
使用grep -o仅提取第一个<html>...</html>
对
grep -oP "^.+?</html>" filename |head -1 | sed -n '/<html>/,/<\/html>/p' > output
但是,就像sed
本身一样,只有当<html></html>
标记始终位于同一行时才会有效。
答案 4 :(得分:0)
使用awk
:
awk 'NR==1,/<\/html>/' input_file
这个单行将从文件的开头到第一个结束的html块开始。如果在第一个html块开始之前有行,它们也会被打印出来。