从 unix 命令行进行基本 xml 解析的最简单方法
Posted
技术标签:
【中文标题】从 unix 命令行进行基本 xml 解析的最简单方法【英文标题】:Simplest way to do basic xml parsing from unix command line 【发布时间】:2012-03-01 07:26:04 【问题描述】:我正在搜索具有某些属性的 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”。从命令行完成此操作的最简单方法是什么?
我想到的一种方法是使用带有 -l 选项的 grep 来过滤掉匹配的文件,然后使用 xargs grep 来提取 Roles 的值。但是,grep 不适用于多行正则表达式。我看到另一个问题表明它可以使用 -Pzo 选项完成,但在我的情况下没有任何运气让它工作。有没有更简单的方法?
【问题讨论】:
您是否有什么特别的原因不想使用 perl 等脚本语言? 对我来说最简单的是从命令行使用Saxon。这是使用XPath on the command line 的示例。这与 shell 脚本相结合,将完全按照您的要求进行。 按照the answer to this question的说法,XMLStarlet似乎很适合这种事情。 不,perl 解决方案会很棒,最好是紧凑的单行,但我不知道编写它的最佳方式。 How to parse XML in Bash?的可能重复 【参考方案1】:以下 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
【讨论】:
不知道 xmllint 可以用来解析 xml。对我来说这是最好的答案,因为它总是被安装,因为它是一个系统依赖项(至少在 CentOS/Redhat/...上)【参考方案2】:我使用基本的 perl/awk 功能(基本上是穷人对标签的解析)制定了几个解决方案。如果您看到仅使用基本 perl/awk 功能的任何改进,请告诉我。我通过设置一个带有我看到特定标签的标志来避免处理多行正则表达式。有点笨拙,但它有效。
perl:
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:
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]'
【讨论】:
【参考方案3】:$ 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>
【讨论】:
【参考方案4】:我通常使用 Perl 的XML::XSH2。您可以在其中以交互方式处理 XML 文件,或编写脚本。该脚本将类似于(未经测试):
for my $file in glob "*.xml"
open $file ;
my $param_value = //param-value[name="Hosts"] ;
if $param_value echo $file $value/value ;
【讨论】:
以上是关于从 unix 命令行进行基本 xml 解析的最简单方法的主要内容,如果未能解决你的问题,请参考以下文章