你有一个 XML Element 和你希望得到的属性=值组合。
虽然您可以有一个简单的awk 或sed 可以从您拥有的单行示例中检索1.2.3,但您确实应该使用XML parser。如果你不这样做,它将来可能不会起作用。
虽然您已经给出了以下属性的全单行示例:
<?xml version="1.0" encoding="utf-8"?>
<pkg-info overwrite-permissions="true" relocatable="false" identifier="com.application.something" version="1.2.3" format-version="2" generator-version="ABC" install-location="/Applications" auth="root">
</pkg-info>
同样的数据也可以:
<?xml version="1.0" encoding="utf-8"?>
<pkg-info overwrite-permissions="true"
relocatable="false" identifier="com.application.something"
version="1.2.3" format-version="2"
generator-version="ABC" install-location="/Applications" auth="root">
</pkg-info>
或者,
<?xml version="1.0" encoding="utf-8"?><pkg-info overwrite-permissions="true" relocatable="false" identifier="com.application.something" version="1.2.3" format-version="2" generator-version="ABC" install-location="/Applications" auth="root"/>
并且仍然被解析为相同的数据。所有三个示例都是有效的 XML,但这里的 awk 或 sed 答案都不能处理除第一个示例之外的任何内容。
对于 XML,'\n'、' '、'\t' 和 '\r' 都是相同的1 但是对于 awk 和 sed,这些字符非常不同的意思。尝试强制使用 awk 或 sed 等面向行的工具来处理 XML 等面向标签的数据非常脆弱。
处理此问题的最佳方法是使用XPath 查询。相关查询是:
/pkg-info/@version
DEMO
鉴于file 具有上述某种有效形式的 XML,您可以使用其中一种方法。
这是一个简单的 Ruby 示例。使用nokogiri xml 解析器通过 xpath 解析感兴趣的属性:
ruby -r nokogiri -e 'doc=Nokogiri::XML($<.read)
puts doc.xpath("/pkg-info").attribute("version").value' file
1.2.3
(您可能需要在系统上安装带有gem install nokogiri 的 nokogiri...)
或者XMLStarlet:
xml sel -t -v '/pkg-info/@version' file
1.2.3
如果您在 Perl 中安装了 XML::XPath 模块(大多数系统都安装了),那么您还有一个名为 xpath 的命令行 XPath 查询工具。你可以这样做:
xpath -q -e '/pkg-info/@version' file
version="1.2.3"
然后通过sed 运行它以获取值:
xpath -q -e '/pkg-info/@version' file | sed -E 's/[^"]*"([^"]*).*/\1/'
1.2.3
请注意,XML 解析器可以处理任何合法版本的 XML 数据。这里的其他sed 或awk 解决方案不会。
如果您的真的非常非常想要使用正则表达式,Perl 是一个更好的选择。这适用于上述所有三个示例:
perl -0777 -lnE 'say $1 if /(?:\s|>)<pkg-info[\s\S]*?\sversion="([^"]+)"/m' file
如果你hafta hafta hafta有一个awk,你可以设置RS-"^$",它具有将整个文件作为一个字符串读取的效果:
- 使用
"<pkg-info " 查找要点。
- 由于这些是属性而不是嵌套标签,因此属性部分中不会有
>。但是,无论<pkg-info 元素如何终止,都必须有一个> 来终止它。
- 现在将
' version=" 值两侧的所有内容替换为""
- 印刷和盈利。
这个awk 适用于我的所有示例;但是,您确实应该使用 XML 解析器。
awk -v RS="^$" '{ x=index($0, "<pkg-info ")
s=substr($0,x)
sub(/[^>]*\sversion="/,"", s)
sub(/".*/,"", s)
print s
}' file
1只要这些字符是insignificant whitespace,在本例中就是...