Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从unix命令行执行基本xml解析的最简单方法_Xml_Perl_Unix_Awk_Grep - Fatal编程技术网

从unix命令行执行基本xml解析的最简单方法

从unix命令行执行基本xml解析的最简单方法,xml,perl,unix,awk,grep,Xml,Perl,Unix,Awk,Grep,我正在搜索具有某些属性的xml文件。例如,包含以下模式的文件: <param-value> <name>Hosts</name> <description>some description</description> <value></value> </param-value> 主人 一些描述 对于这些文件,我想解析另一个标记的值,例如: <param-value>

我正在搜索具有某些属性的xml文件。例如,包含以下模式的文件:

<param-value>
  <name>Hosts</name>
  <description>some description</description>
  <value></value>
</param-value>

主人
一些描述
对于这些文件,我想解析另一个标记的值,例如:

<param-value>
  <name>Roles</name>
  <description>some description</description>
  <value>asdf</value>
</param-value>

角色
一些描述
asdf
并将文件名与“asdf”一起打印出来。从命令行实现这一点最简单的方法是什么

我想到的一种方法是使用grep和-l选项来过滤匹配的文件,然后使用xargs grep来提取角色的值。然而,grep不能很好地处理多行正则表达式。我看到了另一个问题,表明它可以用-Pzo选项来完成,但在我的例子中,没有任何运气让它工作。有更简单的方法吗?

我通常使用Perl。您可以在其中以交互方式处理XML文件,也可以编写脚本。脚本类似于(未测试):


下面的linux命令使用XPath访问XML文件中的指定值

for xml in `find . -name "*.xml"`
do  
echo $xml `xmllint --xpath "/param-value/value/text()" $xml`| awk 'NF>1'
done
匹配XML文件的输出示例:

./test1.xml asdf
./test4.xml 1234

我使用基本的perl/awk功能(基本上是一个穷人对标记的解析)制定了两个解决方案。如果您看到仅使用基本perl/awk功能的任何改进,请告诉我。我避免了处理多行正则表达式,因为我用我看到的特定标记设置了一个标志。有点笨拙,但它能工作

perl:

perl-ne'$h=1,如果m/Host/$r=1,如果m/角色/;如果($h&&m/){$h=0;打印“主机:”,$\u=~/(.*)
$xmlstarlet ed-u/param value/name-v Roles-u/param value/value-v asdf data.xml
角色
一些描述
asdf

您不想使用诸如perl之类的脚本语言有什么特别的原因吗?对我来说,最简单的方法是从命令行使用。下面是一个使用示例。这与shell脚本结合使用,将完全满足您的要求。根据,似乎非常适合这种情况。不,perl解决方案非常好,pre非常紧凑的一行程序,但我不知道编写它的最佳方法。可能可以使用不知道xmllint的副本来解析xml。对我来说,这是最好的答案,因为它总是作为系统依赖项安装的(至少在CentOS/Redhat/…)
./test1.xml asdf
./test4.xml 1234
perl -ne '$h = 1 if m/Host/; $r = 1 if m/Role/; if ($h && m/<value>/) { $h = 0; print "hosts: ", $_ =~ /<value>(.*)</, "\n"}; if ($r && m/<value>/) { $r = 0; print "\nrole: ", $_ =~ /<value>(.*)</, "\n" }'
awk '/Host/ {h = 1} /Role/ {r = 1} h && /<value>/ {h = 0; match($0, "<value>(.*)<", a); print "hosts: " a[1]} r && /<value>/ {r = 0; match($0, "<value>(.*)<", a); print "\nrole: " a[1]}'
$ xmlstarlet ed -u /param-value/name -v Roles -u /param-value/value -v asdf data.xml

<?xml version="1.0"?>
<param-value>
  <name>Roles</name>
  <description>some description</description>
  <value>asdf</value>
</param-value>