如何从shell脚本中的复杂xml文本中获取参数

时间:2014-07-21 15:09:13

标签: xml shell

我在一行中有关于警报数据的非常复杂的xml文本。我想获得名为“emergency”的警报ID。现在这里只有两个警报,但文本是dinamic所以可能会有更多,所以我必须创建一个命令,获取ID,只需要警报的名称。 ID和名称都是唯一的。这是文字:

<get_alerts_response status_text="OK" status="200"><alert id="9028c78d-5e77-4adb-af4c-cb7dcf1ee3dc"><owner><name>aron</name></owner><name>Befejezve</name><comment>Vége a scannek</comment><creation_time>2014-07-01T07:49:41Z</creation_time><modification_time>2014-07-02T09:04:16Z</modification_time><writable>1</writable><in_use>1</in_use><permissions><permission><name>Everything</name></permission></permissions><user_tags><count>0</count></user_tags><condition>Always</condition><event>Task run status changed<data>Done<name>status</name></data></event><method>Email<data>2<name>notice</name></data><data>neferien@gmail.com<name>from_address</name></data><data>6c248850-1f62-11e1-b082-406186ea4fc5<name>notice_attach_format</name></data><data>centrifuga.uranium@gmail.com<name>to_address</name></data><data>8307<name>defense_center_port</name></data><data><name>pkcs12</name></data><data><name>defense_center_ip</name></data></method></alert><alert id="2401db72-043d-46e4-b600-ada35f7f9cc1"><owner><name>aron</name></owner><name>emergency</name><comment></comment><creation_time>2014-07-21T13:37:25Z</creation_time><modification_time>2014-07-21T13:37:25Z</modification_time><writable>1</writable><in_use>0</in_use><permissions><permission><name>Everything</name></permission></permissions><user_tags><count>0</count></user_tags><condition>Severity at least<data>5.5<name>severity</name></data></condition><event>Task run status changed<data>Done<name>status</name></data></event><method>Email<data>sally@example.org<name>to_address</name></data><data>bob@example.org<name>from_address</name></data></method></alert><filters id=""><term>first=1 rows=-1 sort=name</term><keywords><keyword><column>first</column><relation>=</relation><value>1</value></keyword><keyword><column>rows</column><relation>=</relation><value>-1</value></keyword><keyword><column>sort</column><relation>=</relation><value>name</value></keyword></keywords></filters><sort><field>name<order>ascending</order></field></sort><alerts max="-1" start="1"></alerts><alert_count>2<filtered>2</filtered><page>2</page></alert_count></get_alerts_response>

我想我应该做这样的事情,这在我的水平上太难了:

  1. 在文本中找到警报名称(使用变量)的位置(现在是“紧急”)
  2. 在警报名称前查找第一个文本“alert id =”。
  3. 从那里获得下一个34个角色。
  4. 非常感谢您,如果您可以告诉我该怎么做或者您有任何建议!

2 个答案:

答案 0 :(得分:1)

使用awk

awk 'BEGIN { RS = "<alert id=\""; FS = "\"" } /<name>emergency<\/name>/ { print $1 }' file

输出:

2401db72-043d-46e4-b600-ada35f7f9cc1

这是另一个要求的版本:

awk -v name="emergency" 'BEGIN { RS = "<alert id=\""; FS = "\"" } $0 ~ "<name>" name "</name>" { print $1 }' file

答案 1 :(得分:0)

看起来你想用正则表达式做到这一点。但是,你可以(也就是说,我并不是说你特别能做到这一点,从理论上说这是不可能的)不能正确地使用正则表达式解析XML。 XML是一种无上下文的语言,它比基于正则表达式的语法更具表现力。有关更多详细信息,请参阅Chomsky层次结构。

因此,使用适当的XML解析器会更好(也更容易和更稳定)。由于我最熟悉BaseX(完全披露:我也与项目有关),我将使用它。

使用zip版本时,您可以简单地运行文件bin/basex。你想要做的是一个非常简单的XPath表达式,如果你想从命令行或shell脚本运行它,下面应该做。我假设您的数据是一个名为alert.xml的文件,当然您也可以将其作为标准输入的字符串传递。

basex -i alert.xml -q '//alert[name = "emergency"]/@id/string()'