从 XML 中提取属性值

Joh*_*ohn 11 grep xml

使用 Bash,

文件:

<?xml version="1.0" encoding="UTF-8"?>
<blah>
    <blah1 path="er" name="andy" remote="origin" branch="master" tag="true" />
    <blah1 path="er/er1" name="Roger" remote="origin" branch="childbranch" tag="true" />
    <blah1 path="er/er2" name="Steven" remote="origin" branch="master" tag="true" />

</blah>
Run Code Online (Sandbox Code Playgroud)

我尝试了以下方法:

grep -i 'name="andy" remote="origin" branch=".*\"' <filename>
Run Code Online (Sandbox Code Playgroud)

但它返回整行:

<blah1 path="er" name="andy" remote="origin" branch="master" tag="true" />
Run Code Online (Sandbox Code Playgroud)

我想根据以下内容匹配该行:

name="andy"
Run Code Online (Sandbox Code Playgroud)

我只想让它返回:

master
Run Code Online (Sandbox Code Playgroud)

gle*_*man 40

使用 XML 解析器来解析 XML 数据。有了,它就变成了一个 XPath 练习:

$ branch=$(xmlstarlet sel -t -v '//blah1[@name="andy"]/@branch' file.xml)
$ echo $branch
master
Run Code Online (Sandbox Code Playgroud)

  • 这是更好的答案,因为即使在有人决定更改属性顺序后它也会继续工作。 (11认同)
  • @Hermann 或更改空格,或添加另一个属性为`name="andy" branch="foo"` 的元素,或更改字符编码,或在`branch` 属性中放置转义的`\"`,或或...我同意;只需使用 XML 解析器! (4认同)
  • `branch=$(xmllint --xpath 'string(//blah1[@name="andy"]/@branch)' file.xml)` 是 xmllint 的等效命令。 (4认同)
  • @DavidConrad 将其作为答案。 (3认同)

Fre*_*ddy 11

grep

grep -Pio 'name="andy".*branch="\K[^"]*' file
Run Code Online (Sandbox Code Playgroud)
  • -P 启用 perl 正则表达式 (PCRE)
  • -i 忽略大小写
  • -o 只打印匹配的部分

在正则表达式中, the\K是一个零宽度的lookbehind,以匹配 之前的部分\K,但不将其包含在匹配中。

  • 使用 grep 解析 XML 是在自找麻烦。如果属性的顺序发生变化怎么办?如果有其他一些(非`blah1`)元素具有类似的属性怎么办?如果分支名称包含 `\"` 怎么办?另外,为什么是 `-i`?XML 元素和属性名称区分大小写。现在,所有这些都是等待在未来某个时候浮出水面的错误。我建议使用适合这项工作的工具;一个 XML 解析器。 (4认同)

Dav*_*rad 9

使用 xmllint 使用 XPath 提取属性的值:

xmllint --xpath 'string(/blah/blah1[@name="andy"]/@branch)' file.xml
Run Code Online (Sandbox Code Playgroud)

最好使用 XML 解析器来处理 XML,因为属性的顺序可能会发生变化,并且可能会插入换行符,从而导致名称和分支属性位于文件的不同行中。