使用grep和正则表达式从XML检索值

时间:2017-04-24 13:44:07

标签: regex unix grep

我的构建系统返回了以下响应。构建生成多个工件,我想从下面的响应中提取到特定工件的链接。让我们说一下something.exe。

<Artifacts>
    <artifact name="artifact1" version="1.0" buildId="13321123" make_target="beta" branch="branchName" date="2017-04-21 00:31:38.74856-07" 
            endtime="2017-04-21 00:59:54.680601-07"
            status="succeeded"
            change="e850b01967222464ffca02bf94dc711236fa978a"
            released="no">
        <file url="http://build.system.org/path/to/artifact/folder/MD5SUM.txt"/><file url="http://build.system.org/path/to/artifact/folder/SHA1SUM.txt"/><file url="http://build.system.org/path/to/artifact/folder/SHA256SUM.txt"/><file url="http://build.system.org/path/to/artifact/folder/something.exe"/><file url="http://build.system.org/path/to/artifact/folder/something_x64.msi"/>
    </artifact>
</Artifacts>

我想知道一种只提取something.exe的URL的方法。我已经尝试使用管道卷曲输出并使用正则表达式运行grep -E,但这给了我整条线。

curl -s --request GET http://build.system.org/path/to/artifact/folder/api/?build=13321123 | grep -E 'file url='
curl -s --request GET http://build.system.org/path/to/artifact/folder/api/?build=13321123 | | grep -E 'file url="http\S+OVF10.ova"'

有没有办法提取以下内容?

http://build.system.org/path/to/artifact/folder/something.exe

3 个答案:

答案 0 :(得分:2)

在这种情况下,正确的方法是使用XML工具,例如xmlstarlet

但是,当然,这需要一个有效的XML结构。有效的XML结构如下所示:

<artifact name="artifact1" version="1.0" buildId="13321123" make_target="beta" branch="branchName" date="2017-04-21 00:31:38.74856-07" 
        endtime="2017-04-21 00:59:54.680601-07"
       status="succeeded"
       change="e850b01967222464ffca02bf94dc711236fa978a"
       released="no">
    <file url="http://build.system.org/path/to/artifact/folder/MD5SUM.txt"/><file url="http://build.system.org/path/to/artifact/folder/SHA1SUM.txt"/><file url="http://build.system.org/path/to/artifact/folder/SHA256SUM.txt"/><file url="http://build.system.org/path/to/artifact/folder/something.exe"/><file url="http://build.system.org/path/to/artifact/folder/something_x64.msi"/>
</artifact>

命令:

xmlstarlet sel -t -v "//artifact/file[contains(@url,'something.exe')]/@url" -n xmlfile

输出:

http://build.system.org/path/to/artifact/folder/something.exe

-v选项(或--value-of) - XPATH表达式的打印值

如果第一个参数字符串包含第二个参数字符串,则XPATH contains()函数返回true,否则返回false

答案 1 :(得分:1)

正如 RomanPerekhrest 所说,使用xml解析器进行此类任务。对于您的示例输入,您可以使用xmlstarlet,如下所示:

xml sel -t -m 'Artifacts/artifact/file [contains(@url, "something.exe")]' -v @url

输出:

http://build.system.org/path/to/artifact/folder/something.exe

答案 2 :(得分:0)

这个正则表达式应该有效:([\w\d\s]*.exe)"\/>(它搜索一个由(/somename.exe"/>组成的字符串,其中某个人必须由字母,数字或基本空格符号组成(&#34; _&#34; ,&#34; - &#34;,&#34;&#34;)。

$ regex="([\w\d\s]*.exe)"\/>"
$ echo $input | grep -oP "$regex"

尽管如上所述,您不应该使用正则表达式来解析xml,但请使用xml解析器。