我想知道使用shellscript解析XML文件的最佳方法是什么?
如果你已经成功了,如果你能告诉我你是怎么做到的那样
答案 0 :(得分:74)
您可以尝试xmllint
xmllint程序解析一个或多个 在命令中指定的XML文件 行作为xmlfile。它打印各种 输出类型,取决于 选择的选项。它很有用 检测XML代码和XML中的错误 在XML解析器itse
它允许您使用--pattern选项通过xpath选择XML doc中的元素。
在Mac OS X(Yosemite)上,默认安装
在Ubuntu上,如果尚未安装,则可以运行apt-get install libxml2-utils
答案 1 :(得分:21)
这是一个完整的工作示例
如果它只提取电子邮件地址,您可以执行以下操作:
1)假设XML文件spam.xml就像
<spam>
<victims>
<victim>
<name>The Pope</name>
<email>pope@vatican.gob.va</email>
<is_satan>0</is_satan>
</victim>
<victim>
<name>George Bush</name>
<email>father@nwo.com</email>
<is_satan>1</is_satan>
</victim>
<victim>
<name>George Bush Jr</name>
<email>son@nwo.com</email>
<is_satan>0</is_satan>
</victim>
</victims>
</spam>
2)您可以使用以下简短的bash代码获取电子邮件并进行处理:
#!/bin/bash
emails=($(grep -oP '(?<=email>)[^<]+' "/my_path/spam.xml"))
for i in ${!emails[*]}
do
echo "$i" "${emails[$i]}"
# instead of echo use the values to send emails, etc
done
此示例的结果是:
0 pope@vatican.gob.va
1 father@nwo.com
2 son@nwo.com
重要提示:
不要将此用于严肃的事情。这对于玩游戏,获得快速结果,学习grep等都是可以的,但你应该明确地寻找,学习和使用XML解析器进行制作(参见下面的Micha评论)。
答案 2 :(得分:11)
还有xmlstarlet(也适用于Windows)。
答案 3 :(得分:10)
我很惊讶没有人提到xmlsh。使命宣言:
XML的命令行shell基于的理念和设计 Unix Shell
xmlsh提供了熟悉的脚本环境,但具体而言 为脚本xml进程量身定制。
提供了类似shell命令的列表here。
我使用xed
命令,相当于sed
的XML,并允许基于XPath
的搜索和替换。
答案 4 :(得分:8)
试试sgrep。目前尚不清楚你想要做什么,但我肯定不会尝试在bash中编写XML解析器。
答案 5 :(得分:7)
您是否安装了xml_grep?它是某些发行版上基于perl的实用程序标准(它已预先安装在我的CentOS系统上)。不是给它一个正则表达式,而是给它一个xpath表达式。
答案 6 :(得分:4)
一个相当新的项目是xml-coreutils包,其中包含xml-cat,xml-cp,xml-cut,xml-grep,......
答案 7 :(得分:4)
尝试使用xpath。您可以使用它来解析xml树中的元素。
http://www.ibm.com/developerworks/xml/library/x-tipclp/index.html
答案 8 :(得分:2)
这实际上超出了shell脚本的功能。 Shell脚本和标准的Unix工具可以解析面向行的文件,但是当你谈论XML时情况会发生变化。即使是简单的标签也会出现问题:
<MYTAG>Data</MYTAG>
<MYTAG>
Data
</MYTAG>
<MYTAG param="value">Data</MYTAG>
<MYTAG><ANOTHER_TAG>Data
</ANOTHER_TAG><MYTAG>
想象一下,尝试编写一个可以读取其中包含的数据的shell脚本。这三个非常简单的XML示例都显示了不同的方法,这可能是一个问题。前两个示例是XML中完全相同的语法。第三个只是附加了一个属性。第四个包含另一个标签中的数据。简单的sed
,awk
和grep
命令无法捕捉所有可能性。
您需要使用完整的脚本语言,如Perl,Python或Ruby。其中每个模块都具有可以解析XML数据并使底层结构更易于访问的模块。我在Perl中使用XML::Simple。我花了几次尝试来理解它,但它完成了我所需要的,并使我的编程更容易。
答案 9 :(得分:1)
这是一个将XML名称 - 值对和属性转换为bash变量的函数。
http://www.humbug.in/2010/parse-simple-xml-files-using-bash-extract-name-value-pairs-and-attributes/
答案 10 :(得分:1)
这是使用xml_grep的解决方案(因为xpath不是我们可分发的一部分,我不想将它添加到所有生产机器中)...
如果您正在寻找XML文件中的特定设置,并且如果给定树级别的所有元素都是唯一的,并且没有属性,那么您可以使用这个方便的函数:
# File to be parsed
xmlFile="xxxxxxx"
# use xml_grep to find settings in an XML file
# Input ($1): path to setting
function getXmlSetting() {
# Filter out the element name for parsing
local element=`echo $1 | sed 's/^.*\///'`
# Verify the element is not empty
local check=${element:?getXmlSetting invalid input: $1}
# Parse out the CDATA from the XML element
# 1) Find the element (xml_grep)
# 2) Remove newlines (tr -d \n)
# 3) Extract CDATA by looking for *element> CDATA <element*
# 4) Remove leading and trailing spaces
local getXmlSettingResult=`xml_grep --cond $1 $xmlFile 2>/dev/null | tr -d '\n' | sed -n -e "s/.*$element>[[:space:]]*\([^[:space:]].*[^[:space:]]\)[[:space:]]*<\/$element.*/\1/p"`
# Return the result
echo $getXmlSettingResult
}
#EXAMPLE
logPath=`getXmlSetting //config/logs/path`
check=${logPath:?"XML file missing //config/logs/path"}
这将适用于此结构:
<config>
<logs>
<path>/path/to/logs</path>
<logs>
</config>
它也适用于此(但它不会保留换行符):
<config>
<logs>
<path>
/path/to/logs
</path>
<logs>
</config>
如果您有重复&lt; config&gt;或者&lt; logs&gt;或者&lt; path&gt;,然后它只返回最后一个。如果找到多个匹配项,您可以修改函数以返回数组。
仅供参考:此代码适用于使用GNU BASH 4.1.2的RedHat 6.3,但我不认为我正在做任何特别的事情,所以应该在任何地方工作。
注意:对于任何刚接触脚本的人,请确保使用正确类型的引号,这三个代码都在此代码中使用(正常单引号'=文字,后退单引号`=执行,双引号'=组)