【问题标题】:awk : search for a keyword in XML and write to another fileawk : 在 XML 中搜索关键字并写入另一个文件
【发布时间】:2016-11-06 22:58:01
【问题描述】:

我的输入 XML 在下面。如果存在“SEARCH”关键字,我需要在我的输入 XML 中进行搜索。如果存在,我需要 将 <record> 中的内容复制到 </record> 并写入另一个 XML 文件。

输入 XML

<XML>
<record category="xyz">
<person ssn="" e-i="E">
<title xsi:nil="true"/>
<position xsi:nil="true"/>
<details>
<names>
<first_name/>
<last_name></last_name>
</names>
<aliases>
<alias>CDP</alias>
</aliases>
<keywords>
<keyword xsi:nil="true"/>
<keyword>SEARCH</keyword>
</keywords>
<external_sources>
<uri>http://www.google.com</uri>
<detail>SEARCH is present in abc for xyz reason</detail>
</external_sources>
</details>
</person>
</record>
<record category="abc">
<person ssn="" e-i="F">
<title xsi:nil="true"/>
<position xsi:nil="true"/>
<details>
<names>
<first_name/>
<last_name></last_name>
</names>
<aliases>
<alias>CDP</alias>
</aliases>
<keywords>
<keyword xsi:nil="true"/>
<keyword>DONTSEARCH</keyword>
</keywords>
<external_sources>
<uri>http://www.google.com</uri>
<detail>SEARCH is not present in abc for xyz reason</detail>
</external_sources>
</details>
</person>
</record>
</XML>

我现在的代码:

NR==FNR {
keywordArray[NR]=$0;
next;
}

/<record / { i=1 }
i { a[i++]=$0 }
/<\/record>/ {
    if (found) {
        for (i=1; i<=length(a); ++i) print a[i] >> output.xml
    }
    i=0;
    found=0
}
$0 ~ "<keyword>"SEARCH"</keyword>" { found=1 }

当前代码存在问题:

代码没有搜索“SEARCH”,也没有向 output.xml 写入任何内容

预期输出:

<record category="xyz">
<person ssn="" e-i="E">
<title xsi:nil="true"/>
<position xsi:nil="true"/>
<details>
<names>
<first_name/>
<last_name></last_name>
</names>
<aliases>
<alias>CDP</alias>
</aliases>
<keywords>
<keyword xsi:nil="true"/>
<keyword>SEARCH</keyword>
</keywords>
<external_sources>
<uri>http://www.google.com</uri>
<detail>SEARCH is present in abc for xyz reason</detail>
</external_sources>
</details>
</person>
</record>

【问题讨论】:

  • 股票建议:不要使用像 awk 这样的面向行的工具来操作 XML 数据。请改用xsltprocxmlstarlet 等支持XML 的工具。
  • 即xmlstarlet sel -t -m 'XML/record/person/details/keywords/keyword[.="SEARCH"]' -c '../../../..' foo.xml > bar.xml跨度>
  • @tomc : 为什么上面的代码中需要'../../../..'
  • 代码匹配keyword元素,然后选择与匹配相对的record元素,即父级的父级等。但是,有更简单的方法可以做到这一点.

标签: xml bash shell search awk


【解决方案1】:

嗯,它并不完美,但也许你可以改进:

BEGIN {
  FS="\n"        # field separator to enter
  OFS="\n"       # output separator as well
  RS="</record>" # records end at </record>
} 
$0 ~ /<keyword>SEARCH<\/keyword>/'     # print record if SEARCH matched

【讨论】:

    【解决方案2】:

    有了xmlstarlet,你可以使用这个:

     xmlstarlet sel -t -c "//record[.//keyword/text()='SEARCH']" foo.xml
    

    【讨论】:

    • @user2488578 正如@Michael Vehrs 所指出的,我的(故意明确的)版本中的'../../../..'是-copy 上面的xml 节四个父母,其中“搜索”是-matched。
    猜你喜欢
    • 1970-01-01
    • 2016-05-14
    • 2017-03-05
    • 1970-01-01
    • 1970-01-01
    • 2016-02-08
    • 2020-08-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多