如何使用SED提取特定的XML节点

时间:2018-12-11 18:12:15

标签: xml unix sed

第一次在这里发布,但不是第一次使用Stack Overflow作为资源。必须说这个网站是我整体工作不可或缺的。

以前,我已经以多种方式使用sed,但似乎并无法弄清楚如何且仅当其子节点之一满足某些条件时才能返回完整的XML节点。我知道如何使用2地址约定(/START/END/command),但只需要将结果限制为特定的匹配子节点即可。

示例:

<entity id="001">
    <name>Jane Doe</name>
    <country>US</country>
</entity>
<entity id="002">
    <name>Jose Reyes</name>
    <country>Mexico</country>
</entity>
<entity id="003">
    <name>Juan Dela Cruz</name>
    <country>Philippines</country>
</entity>
<entity id="004">
    <name>William Shatner</name>
    <country>US</country>
</entity>

如果我想返回ID为003的完整实体节点,可以使用以下命令:

sed -n '/entity id="003"/,/<\/entity>/p'

但是,如果我想返回与国家US相匹配的完整实体节点,该如何处理?

如果您能指出我的一般方向,我不介意自己做这项工作。实际上,我确实更喜欢用勺子喂食。

谢谢!

1 个答案:

答案 0 :(得分:1)

您可能会在类似问题的评论中看到,处理XML最好的东西是为处理XML而设计的工具,而不是像sed或awk这样的常规文本处理工具。

例如,如果您有权访问xmlstarlet

$ xmlstarlet sel -t -c "//entity[country = 'US']" file.xml
<entity id="001">
    <name>Jane Doe</name>
    <country>US</country>
</entity><entity id="004">
    <name>William Shatner</name>
    <country>US</country>
</entity>

尤其是如果您要使用XML多一点,我将投入精力研究更适合于XML解析的可用命令行工具。

如果您真的很困惑,那么awk会比sed更好,并且awk应该可以在以下任何位置使用:

$ cat a.awk

/<entity id/ { f = 1; s = "" }

f { s = s ? (s ORS $0) : $0 }

/<country>US</ { f = 2 }

/<\/entity>/ {
    if (f == 2) print s
    f = 0
}

$ awk -f a.awk file.xml
  <entity id="001">
    <name>Jane Doe</name>
    <country>US</country>
  </entity>
  <entity id="004">
    <name>William Shatner</name>
    <country>US</country>
  </entity>