在bash脚本中提取XML值

时间:2013-06-27 02:48:20

标签: xml bash shell sed

我正在尝试从已作为变量读入我的脚本的xml文档中提取值。原始变量 $ data 是:

<item> 
  <title>15:54:57 - George:</title>
  <description>Diane DeConn? You saw Diane DeConn!</description> 
</item> 
<item> 
  <title>15:55:17 - Jerry:</title> 
  <description>Something huh?</description>
</item> 

我希望提取第一个标题值,所以

15:54:57 - George:

我一直在使用sed命令:

title=$(sed -n -e 's/.*<title>\(.*\)<\/title>.*/\1/p' <<< $data)

但这只输出第二个标题值:

15:55:17 - Jerry:

有谁知道我做错了什么? 谢谢!

3 个答案:

答案 0 :(得分:66)

正如Charles Duffey所述,XML解析器最好使用适当的XML解析工具进行解析。对于一次性工作,以下工作应该有效。

grep -oPm1 "(?<=<title>)[^<]+"

测试:

$ echo "$data"
<item> 
  <title>15:54:57 - George:</title>
  <description>Diane DeConn? You saw Diane DeConn!</description> 
</item> 
<item> 
  <title>15:55:17 - Jerry:</title> 
  <description>Something huh?</description>
$ title=$(grep -oPm1 "(?<=<title>)[^<]+" <<< "$data")
$ echo "$title"
15:54:57 - George:

答案 1 :(得分:21)

XMLStarlet或其他XPath引擎是这项工作的正确工具。

例如,data.xml包含以下内容:

<root>
  <item> 
    <title>15:54:57 - George:</title>
    <description>Diane DeConn? You saw Diane DeConn!</description> 
  </item> 
  <item> 
    <title>15:55:17 - Jerry:</title> 
    <description>Something huh?</description>
  </item>
</root>

...您只能使用以下内容提取第一个标题:

xmlstarlet sel -t -m '//title[1]' -v . -n <data.xml

尝试将sed用于此作业是troublesome。例如,如果标题具有属性,则基于正则表达式的方法将不起作用;不会处理CDATA部分;将无法正确识别命名空间映射;无法确定所记录的XML的一部分是否被注释掉;不会忽略属性引用(例如将Brewster &amp; Jobs更改为Brewster & Jobs),等等。

答案 2 :(得分:7)

我同意Charles Duffy认为正确的XML解析器是正确的方法。

但是关于你的sed命令有什么问题(或者你是故意这么做的?)。

  • $data未被引用,因此$data受到shell的单词拆分,文件名扩展以及其他内容的限制。其中一个后果是不保留XML片段中的间距。

因此,鉴于您的特定XML结构,此修改后的sed命令应该可以正常工作

title=$(sed -ne '/title/{s/.*<title>\(.*\)<\/title>.*/\1/p;q;}' <<< "$data")

基本上对于包含title的行,在标签之间提取文本,然后退出(这样就不会提取第二个<title>