有人可以帮助我将xml数据导入shell脚本
这是我的要求。
如果CHILD值大于100,我需要打印CHILD值以及CHILD和parent的属性值
这是我的数据
<mydata>
<parent detail="school1">
<CHILD attribute="0">0</CHILD>
<CHILD attribute="1">1932</CHILD>
<CHILD attribute="2">0</CHILD>
<CHILD attribute="3">500</CHILD>
<CHILD attribute="4">0</CHILD>
<CHILD attribute="5">0</CHILD>
<CHILD attribute="6">7819</CHILD>
<CHILD attribute="7">0</CHILD>
<CHILD attribute="8">299</CHILD>
<CHILD attribute="9">0</CHILD>
</parent>
<parent detail="school2">
<CHILD attribute="0">1</CHILD>
<CHILD attribute="1">7000</CHILD>
<CHILD attribute="2">0</CHILD>
<CHILD attribute="3">0</CHILD>
<CHILD attribute="4">600</CHILD>
<CHILD attribute="5">0</CHILD>
<CHILD attribute="6">11674</CHILD>
<CHILD attribute="7">0</CHILD>
<CHILD attribute="8">489</CHILD>
<CHILD attribute="9">0</CHILD>
</parent>
</mydata>
我的外部文件值是这样的 childvalue_limits.txt文件
attribute0=100
attribute1=60
attribute3=80
attribute4=90
attribute5=100
attribute6=90
attribute7=50
attribute8=80
attribute9=70
我需要将此文件作为参数传递给脚本,并将这些值动态地置于条件中。
当前代码
sed 's|><|>\n<|g' $WORKING_PATH/xml_detail.log | awk -F'"|<|>' '/parent detail/{p=$3} /CHILD attribute/{att=$3;val=$5;if(val>100)print "child value on " p, "attribute "att,"is at value: "val ,"\n"}'
当前输出
child value on school2 attribute 1 is at value 1000
child value on school2 attribute 4 is at value 600
.....
.....
所需的输出应该是这样的
child value on school2 attribute 1 is at value 1000 and threshold is 60
child value on school2 attribute 4 is at value 600 and threshold is 90
.....
.....
请注意:阈值是通过名为childvalue_limits.txt的单独文件传递给if条件的动态值
答案 0 :(得分:1)
您无法(正确)使用正则表达式解析XML。 XML是一种无上下文的语言,它比基于正则表达式的语法更具表现力。有关详细信息,请参阅Chomsky层次结构。这也是你在使用正则表达式时遇到新行问题的原因。
因此,使用适当的XML解析器会更好(也更容易和更稳定)。由于我最熟悉BaseX(完全披露:我也与项目有关),我将使用它。
使用zip版本时,您可以简单地运行文件bin/basex
。以下XPath 3.0表达式应该为您提供正确的输出,只需连接不同的值:
for $c in /mydata/parent/CHILD[. > 100] return $c/parent::parent/@detail || " " || $c/@attribute || " " || $c/data() || " "
假设您的xml文件名为mydata.xml
,您可以通过发出以下命令来执行此XPath(即可以在您的shell脚本中完成):
basex -i mydata.xml -q 'for $c in /mydata/parent/CHILD[. > 100] return $c/parent::parent/@detail || " " || $c/@attribute || " " || $c/data() || " "'
答案 1 :(得分:0)
再次编辑
好的,我已将代码更改为读取输入限制的文件。它看起来很复杂,但事实并非如此 - 你可以删除所有包含单词&#34; DEBUG&#34;如果你愿意的话。 #
是评论的开头。
#!/bin/bash
awk -F'"|<|>' '
FNR==NR {
split($0,f,"="); # Split line on "=" sign into array f[]
gsub(/[[:alpha:]]/,"",f[1]); # Remove non-digits
limits[f[1]]=f[2]; # Save for comparison later
print "DEBUG: limits[",f[1],"]=",f[2];
next
}
/parent detail/ {
p=$3
print "DEBUG: parent detail=",p;
}
/CHILD attribute/ {
att=$3;val=$5;
print "DEBUG: att=",att,",val=",val;
if(val>limits[att])print p,att,val,limits[att]
}
' limits.txt xml
您会在脚本末尾看到它同时读取您的文件 - limits.txt
和xml
。在脚本中,以FNR==NR
开头的花括号中的块意味着以下代码仅适用于读取和解析limits.txt
。
如果您想查看没有DEBUG
消息的输出,请运行
./script | grep -v DEBUG
<强> EDITED 强>
使用修改后的数据,您的代码可以正常使用。这是我的输出:
node2 1 1932
node2 6 7819
node1 1 1924
node1 6 11674
我认为您的意思是要避免使用XML解析器,只使用awk
和sed
之类的标准工具来实现这一目标,因此我将使用awk
awk -F'"|<|>' '/parent detail/{p=$3} /CHILD attribute/{att=$3;val=$5;if(val>100)print p,att,val}' xml
<强>输出:强>
school1 1 1932
school1 3 500
school1 6 7819
school1 8 299
school2 1 7000
school2 4 600
school2 6 11674
school2 8 489
因此,它将分隔符设置为"
,<
或>
中的任何一个。然后,当它看到带有&#34;父细节&#34;它将值保存在p
中。当它看到带有单词CHILD attribute
的行时,它会提取属性和值。如果该值超过100,则打印父,属性和值。
它假设您的XML位于名为xml
的文件中。