使用ksh脚本从XML中提取数据

使用ksh脚本从XML中提取数据,xml,parsing,ksh,Xml,Parsing,Ksh,我在这个话题上问的第一个问题由于缺乏信息而被关闭了。因此,再次询问这个问题,并添加更多细节 我必须从xml文件中提取一个标记中给定的值,我必须使用ksh(我可以用perl解决这个问题,但我必须使用ksh,不能使用像xmlsh这样的第三方工具) sample.xml <?xml version="1.0" standalone="yes" ?> <parent_one> <parent_two> <Pool> <pool

我在这个话题上问的第一个问题由于缺乏信息而被关闭了。因此,再次询问这个问题,并添加更多细节

我必须从xml文件中提取一个标记中给定的值,我必须使用ksh(我可以用perl解决这个问题,但我必须使用ksh,不能使用像xmlsh这样的第三方工具)

sample.xml

<?xml version="1.0" standalone="yes" ?>
<parent_one>
  <parent_two>
    <Pool>
      <pool_name>ABC</pool_name>
      <percent_full>79</percent_full>
      <pool_state>Enabled</pool_state>
    </Pool>
    <Pool>
      <pool_name>DEF</pool_name>
      <percent_full>40</percent_full>
      <pool_state>Enabled</pool_state>
    </Pool>
    <Pool>
      <pool_name>XYZ</pool_name>
      <percent_full>40</percent_full>
      <pool_state>Disabled</pool_state>
    </Pool> 
    <Totals>
      <total_tracks>4546456</total_tracks>
      <percent_full>48</percent_full>
    </Totals>
  </parent_two>
</parent_one>

基础知识
79
启用
DEF
40
启用
XYZ
40
残废
4546456
48
ksh脚本应该读取sample.xml并从pool_name标记打印ABC、DEF,因为相应的pool_state标记已启用。它不应该打印XYZ,因为它的pool_状态标记已禁用

ksh脚本将读取sample.xml并输出以下内容

ABC

DEF

这在ksh中是可行的,还是我必须使用perl来实现这一点?

话虽如此(我的评论是试图在没有合适的XML解析器的情况下解析XML),让我们使用sed/awk来尝试一下,而不是纯ksh。作为基础,删除所有的<代码> >代码>块,其中有“代码> POLLYSTATE < /COD>设置为<代码>禁用< /代码>,然后获取包含<代码> POLLYNEXNE/CODE >的行,并捕获标签之间的值。如果您的
xml
文件看起来像您的示例,那么它应该可以工作,但如果不工作,它肯定会崩溃

awk '
    /<Pool>/ { rec=""; f=1 }
    f {rec = rec $0 ORS}
    /<\/Pool>/ {
        if (f && (rec !~ "<pool_state>Disabled</pool_state>"))
            printf "%s", rec
            f=0
    }' sample.xml |
grep pool_name |
sed 's#.*>\([^<]*\)<.*#\1#g'
awk'
//{rec=”“;f=1}
f{rec=rec$0 ORS}
// {
如果(f&(rec!~“禁用”))
打印文件“%s”,记录
f=0
}'sample.xml|
grep池名称|

sed的#.*>\([^我已经用(n)awk对奇数格式文件进行了大量解析。从技术上讲,这可以用ksh来完成,但是awk(和perl)更容易

以下示例使用了
awk
中的开始结束构造,它只处理开始结束模式之间的行。(在这种情况下,

除此之外,它很简单,为了清晰起见,使用了模仿xml元素的变量

awk '/<Pool>/,/<\/Pool>/ {
    if (/<pool_state>/) {
        pool_state=(/<pool_state>Enabled<\/pool_state>/)
    }
    if (/<pool_name>/) {
        if ( gsub(/.*<pool_name>|<\/pool_name>.*/,"") ) {
          pool_name=$0
        }
    }
    if (/<\/Pool>/) {
      if (pool_name && pool_state)
        print pool_name
      unset pool_name
      unset pool_state
    }
}' sample.xml
awk'/,//{
如果(//){
池状态=(/Enabled/)
}
如果(//){
if(gsub(/.*.*/,“”){
池名称=$0
}
}
如果(//){
if(池名称和池状态)
打印池名称
取消设置池名称
取消设置池状态
}
}'sample.xml

当xml格式不正确时,当多个池元素在一行中列出时,这段代码将失败得可怕。

解决此问题的明智方法是调用
xmllint--xpath
,或者调用您喜欢的Python/Ruby/Perl等xml库

否则,您可以看看Roland Mainz的XML示例,并根据您的需要对其进行扩展


如果您对此非常认真,您可能会考虑为ksh编写libxml2绑定。我认为还没有人这样做。

您真的不想自己解析XML。当您声明不允许使用perl时,为什么还要问您是否必须使用perl?哇,我不知道您可以在awk中这样做。今天学习了一些新的东西。ThanksAdrian,你的解决方案起作用了,但是我要和亨克的解决方案一起去,因为我更容易理解:“谢谢你,哪一个都适合你!只要记住,一旦你开始做更复杂的事情,你就应该考虑切换到“正确的”工具: