I am working on a script, which returns output in xml format and wanted to print just the value of a particular attribute.
我正在编写一个脚本,它返回xml格式的输出,并只想打印特定属性的值。
As an example, here is the output of the script :
例如,下面是脚本的输出:
~#] ./test.sh resource list --platform=centos
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ResourcesResponse>
<Status>Success</Status>
<Resource id="11087" name="centos"
Now, I wanted to print only the Resource id which is 11087. When I used awk along with NR, it returns as below :
现在,我只想打印11087的资源id。当我使用awk和NR时,它返回如下:
~#] ./test.sh resource list --platform=centos | awk 'NR==4{print $2}'
id="11087"
Could you please help know how to print only the value, i.e 11087
你能帮忙知道如何只打印值i吗?e 11087
4 个解决方案
#1
3
Here is another solution using xmlstarlet
with XPath query :
下面是另一个使用xmlstarlet与XPath查询的解决方案:
$ ./test.sh resource list --platform=centos|xmlstarlet sel -T -t -m '/ResourcesResponse/Resource/@id' -v '.' -n
11087
$ xmlstarlet sel -T -t -m '/ResourcesResponse/Resource/@id' -v '.' -n < <(./test.sh resource list --platform=centos)
11087
It's always better to use tools optimized for XML parsing (xmlstarter
, xmllint
, or more powerful shells languages like perl, python, php cli mode, etc.).
最好使用为XML解析而优化的工具(xmlstarter、xmllint或更强大的shell语言,如perl、python、php cli mode等)。
#2
2
Using sed
:
使用sed:
~#] ./test.sh resource list --platform=centos | sed -nr '4 s/.*id="([^"]+)".*/\1/p'
11087
Notes:
注:
-
The
-n
option tosed
tells it not print anything unless we explicitly ask it to.sed的-n选项告诉它不打印任何内容,除非我们明确地要求它这样做。
-
The
-r
option tosed
tells it to use extended regular expressionssed的-r选项告诉它使用扩展正则表达式
-
The
sed
command4 s/old/new/p
tells it to operate on only on line 4 and, on that line, look forold
and replace it withnew
and, only if that substitution happened, print the line.sed命令4 s/old/new/p只告诉它在第4行上操作,在这一行中,查找旧的并使用new替换它,只有在发生替换时,打印行。
-
In our case, the value of
old
is.*id="([^"]+)".*/
. Since this starts with.*
and ends with.*
, it matches the whole line. It also captures the value of the id in match variable 1.在我们的例子中,旧的价值。* id = "([^]+)。* /。因为它以。*开头,以。*结尾,所以它与整条线相匹配。它还捕获匹配变量1中的id值。
-
The value of
new
is simply\1
which is the value of the id.new的值只是\1,它是id的值。
#3
2
This awk
should give what you want.
这个awk应该给你想要的。
awk -F\" 'NR==4{print $2}' file
11087
By setting Field Separator to "
your data are in the second field.
通过将字段分隔符设置为“您的数据位于第二个字段中”。
To make sure you get correct id
, I would have used:
为了确保您得到正确的id,我将使用:
awk -F\" '/Resource id/ {print $2}' file
11087
#4
2
grep variant:
grep变体:
grep -m1 -oP '(?<=id=")[0-9]*(?=")' file
Or with input piped from your command:
或使用来自命令的输入管道:
~#] ./test.sh resource list --platform=centos | grep -m1 -oP '(?<=id=")[0-9]*(?=")'
11087
Explanation: Print only (-o
) first match (-m1
) of number ([0-9]*
) prefixed by id="
((?<=id=")
) & followed by a "
((?=")
).
说明:只打印(-o)第一次匹配(-m1)的数字([0-9]*),前缀为id=" ((?<=id="),后面是"(?=")。
#1
3
Here is another solution using xmlstarlet
with XPath query :
下面是另一个使用xmlstarlet与XPath查询的解决方案:
$ ./test.sh resource list --platform=centos|xmlstarlet sel -T -t -m '/ResourcesResponse/Resource/@id' -v '.' -n
11087
$ xmlstarlet sel -T -t -m '/ResourcesResponse/Resource/@id' -v '.' -n < <(./test.sh resource list --platform=centos)
11087
It's always better to use tools optimized for XML parsing (xmlstarter
, xmllint
, or more powerful shells languages like perl, python, php cli mode, etc.).
最好使用为XML解析而优化的工具(xmlstarter、xmllint或更强大的shell语言,如perl、python、php cli mode等)。
#2
2
Using sed
:
使用sed:
~#] ./test.sh resource list --platform=centos | sed -nr '4 s/.*id="([^"]+)".*/\1/p'
11087
Notes:
注:
-
The
-n
option tosed
tells it not print anything unless we explicitly ask it to.sed的-n选项告诉它不打印任何内容,除非我们明确地要求它这样做。
-
The
-r
option tosed
tells it to use extended regular expressionssed的-r选项告诉它使用扩展正则表达式
-
The
sed
command4 s/old/new/p
tells it to operate on only on line 4 and, on that line, look forold
and replace it withnew
and, only if that substitution happened, print the line.sed命令4 s/old/new/p只告诉它在第4行上操作,在这一行中,查找旧的并使用new替换它,只有在发生替换时,打印行。
-
In our case, the value of
old
is.*id="([^"]+)".*/
. Since this starts with.*
and ends with.*
, it matches the whole line. It also captures the value of the id in match variable 1.在我们的例子中,旧的价值。* id = "([^]+)。* /。因为它以。*开头,以。*结尾,所以它与整条线相匹配。它还捕获匹配变量1中的id值。
-
The value of
new
is simply\1
which is the value of the id.new的值只是\1,它是id的值。
#3
2
This awk
should give what you want.
这个awk应该给你想要的。
awk -F\" 'NR==4{print $2}' file
11087
By setting Field Separator to "
your data are in the second field.
通过将字段分隔符设置为“您的数据位于第二个字段中”。
To make sure you get correct id
, I would have used:
为了确保您得到正确的id,我将使用:
awk -F\" '/Resource id/ {print $2}' file
11087
#4
2
grep variant:
grep变体:
grep -m1 -oP '(?<=id=")[0-9]*(?=")' file
Or with input piped from your command:
或使用来自命令的输入管道:
~#] ./test.sh resource list --platform=centos | grep -m1 -oP '(?<=id=")[0-9]*(?=")'
11087
Explanation: Print only (-o
) first match (-m1
) of number ([0-9]*
) prefixed by id="
((?<=id=")
) & followed by a "
((?=")
).
说明:只打印(-o)第一次匹配(-m1)的数字([0-9]*),前缀为id=" ((?<=id="),后面是"(?=")。