【问题标题】:Multiline grep with specific text带有特定文本的多行 grep
【发布时间】:2019-10-08 12:33:16
【问题描述】:

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

我需要查看至少有一个 <C_tag> 的那些 A 标记(及其子标记,因此标记的全部内容)。

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

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

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

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

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

【问题讨论】:

  • xml file - 也许使用 xml 感知解析器? xmllint?

标签: bash awk grep pcregrep


【解决方案1】:

跟进 xmllint 评论:

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

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

输出:

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

【讨论】:

    【解决方案2】:

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

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

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

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

    如果您有更通用的解决方案适用于awkpcregrep,请与我分享。它们在这里会很好,因为它们只使用模式。

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

    【讨论】:

      【解决方案3】:

      如果文件打印得很漂亮(或遵循类似的规则),可以编写小的 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
      

      【讨论】:

        猜你喜欢
        • 2021-02-26
        • 1970-01-01
        • 1970-01-01
        • 2014-06-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-11
        相关资源
        最近更新 更多