0

有一个xml文件,<A_tag>里面有很多-s。

我需要查看那些至少有一个<C_tag>.

所以这个块应该匹配(因此包含在结果中):

<A_tag>
    ...
    ...
    <C_tag attr1="" ... attrn="" />
    ...
</A_tag>

我尝试使用 pcregrep,但我不知道如何判断任何大于 1 个字符的块结尾(并且</A_tag>比这更长,但例如[^>]regexp 对我来说也很容易)。

我也尝试过 awk,但也无法用它来管理目标。

如果有经验的人可以帮助我,请让您的命令也用空行分隔找到的块,这样我可以了解更多信息。

4

3 回答 3

2

跟进 xmllint 评论:

xmllint --xpath '(//A_tag/C_tag/..)' x.xml

将在 A_TAG 下寻找 C_TAG,然后显示父 A_TAG。

输出:

<A_tag>
    <C_tag attr1="" attrn=""/>
</A_tag>
于 2019-10-08T12:58:12.923 回答
0

是的,就我而言,这是解决方案:

xmllint --shell x.xml <<< 'xpath //A_tag//C_tag/ancestor::A_tag'

这是因为我的xmllint版本不支持--xpath选项。此外,C_tag可以是 的任何后代A_tag,而不仅仅是直接孩子(我没有澄清问题)。但是,dash-o 的答案似乎是正确的。

我唯一的问题是我正在使用的这个 xml 文件包含 450 万行,xmllint结果很慢 - 因为它确实解析了文件。

如果您有更通用的解决方案,可以与awkor一起使用pcregrep,请与我分享。它们在这里会很好,因为它们只使用模式。

否则我明天会接受原来的答案。

于 2019-10-09T08:13:38.453 回答
0

如果文件打印得很漂亮(或遵循类似的规则),可以编写小的 awk 脚本,并且只作用于 a_tag 和 c_tag 行:

awk '
/<A_tag>/      { in_a=$0 ; c="" ; next }
in_a           { in_a = in_a RS $0}
/<C_tag/       { c=$0 ; next }
/<\/A_tag>/    { if ( in_a && c ) { print in_a ; in_a="" ; c=""} }
' x.xml
于 2019-10-10T10:17:23.687 回答