外壳如何在关键字范围内选择内容?



这是一个HTML文件,其中包含大量<section>... </section>内容在一个HTML文件中,其格式如下。

<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>
<section>
<div>
<header><h2>This is a title (RfQVthHm)</h2></header>
More HTML codes...
</div>
</section>
<section>
<div>
<header><h2>This is a title (UaHaZWvm)</h2></header>
More HTML codes...
</div>
</section>
<section>
<div>
<header><h2>This is a title (vxzbXEGq)</h2></header>
More HTML codes...
</div>
</section>
</body>
</html>

我需要提取第二个<section>...</section>内容。

这是预期的输出。

<section>
<div>
<header><h2>This is a title (UaHaZWvm)</h2></header>
More HTML codes...
</div>
</section>

我注意到我可以先寻找UaHaZWvm字符(前面 2 行),直到遇到下一个</section>

OP的努力(在评论中提到):grep -o "hi.*bye" file

这可以使用awksedgrep工具完成吗?

由于您使用的是 HTML,因此使用可识别格式的工具(如xmllint或其他一些允许您使用 XPath 表达式提取文档部分的程序)要简单得多,也更好:

$ xmllint --html --xpath '//section[2]' input.html 2>/dev/null
<section>
<div>
<header><h2>This is a title (UaHaZWvm)</h2></header>
More HTML codes...
</div>
</section>               

(xmllint给出了很多关于标签的错误;我不认为它真的支持HTML5?无论如何,这就是为什么上面有标准错误的重定向。


使用W3C的HTML-XML-utils程序集合中的hxselect替代。它使用 CSS 选择器来指定要从文档中获取的内容,而不是 XPath:

hxselect 'section:nth-child(2)' < input.html

有了您显示的示例,您能否尝试以下操作。用GNUawk编写和测试,应该可以在任何awk工作。

awk '
/^</section>/{
if(found1==2 && found2==1){
print val
exit
}
found2++
}
/<section>/{
found1++
}
found1==2{
val=(val?val ORS:"")$0
}
'  Input_file

说明:为上述添加详细说明。

awk '                             ##Starting awk program from here.
/^</section>/{                   ##Checking condition if line starts from </section> here.
if(found1==2 && found2==1){     ##Checking condition if found1 is 2 AND found2 is 1 then do following.
print val                     ##printing val here.
exit                          ##exiting from program from here.
}
found2++                        ##Increasing found2 with 1 here.
}
/<section>/{                      ##Checking condition if line has <section> then do following.
found1++                        ##Increasing found1 with 1 here.
}
found1==2{                        ##Checking if found1 is 2 then do following.
val=(val?val ORS:"")$0          ##Creating val and keep adding lines into it.
}
'

从您的问题中不清楚您是否尝试打印第 2 部分(无论它包含什么)或包含 UaHaZWvm 的部分(无论它以什么顺序出现),所以这里有两种解决方案:

要打印第 2 部分:

$ awk -v RS= -v ORS='nn' 'NR==3' file
<section>
<div>
<header><h2>This is a title (UaHaZWvm)</h2></header>
More HTML codes...
</div>
</section>

要打印包含UaHaZWvm的任何部分:

$ awk -v RS= -v ORS='nn' '/UaHaZWvm/' file
<section>
<div>
<header><h2>This is a title (UaHaZWvm)</h2></header>
More HTML codes...
</div>
</section>
gawk '/<section>/,/</section>/{ s=s $0; }
/</section>/{ i++; print i, s; s=""; }
END{ if(s!="") print i,s}' some.html

将打印所有部分,例如:

1 <section><div><header><h2>This is a title (RfQVthHm)</h2></header>More HTML codes...</div></section>
2 <section><div><header><h2>This is a title (UaHaZWvm)</h2></header>More HTML codes...</div></section>
3 <section><div><header><h2>This is a title (vxzbXEGq)</h2></header>More HTML codes...</div></section>

这适用于Patterns,请参阅来自 gawk 或 awk 的手册页。

只返回第二个应该很容易...

编辑:(基于Ed M的评论。

gawk '/<section>/{ i=(i<0?-i:i); i++; }
/</section>/{ i=-i; }
{ a[i]=a[i] $0 }
END{ print a[2] }' some.html

使用grep您可以执行以下操作:grep 'UaHaZWvm' -B2 -A3 some.html其中输出:

<section>
<div>
<header><h2>This is a title (UaHaZWvm)</h2></header>
More HTML codes...
</div>
</section>

在段落模式下使用awk

awk -v RS= -v ORS='nn' '/UaHaZWvm/' file
<section>
<div>
<header><h2>This is a title (UaHaZWvm)</h2></header>
More HTML codes...
</div>
</section>

更新我的解决方案,希望它对其他人有用。

这是结合grep的解决方案,使用-B选项设置内容的开头,使用-A选项输出其余内容(通常10,000行就足够使用了),然后使用sedawk来定位结束关键字。

awk

cat test.html | grep 'UaHaZWvm' -B2 -A10000 | awk 'NR==1,/</section>/'

塞德

cat test.html | grep 'UaHaZWvm' -B2 -A10000 | sed -n '1,/</section>/p'

最新更新