我有一些 XML,看起来像这样:
<artifactId>myproject</artifactId>
<version>1.14.0-SNAPSHOT</version>
我想提取版本,即1.14.0-SNAPSHOT
.我知道如何使用两个 grep 和一个管道来做到这一点:
$ grep -A1 "<artifactId>myproject</artifactId>" pom.xml | grep -Eo "\d+.\d+.\d+-SNAPSHOT"
我怎样才能将两者合而为一?我使用 awk 还是 sed 来完成这项任务会更好吗?
答案1
如果你确定<version>
在下一行之后myproject
sed -n '
\|<artifactId>myproject</artifactId>|{
n #get next line
s|[[:blank:]]*</\?version>[[:blank:]]*||gp #remove tags and print
}
' pom.xml
或者如果你有正则表达式
grep -zoP '<artifactId>myproject</artifactId>\s*\n\s*<version>\K[^<]+' pom.xml
答案2
您在评论中提到您想要一些便携式的东西。这是令人钦佩的,但我真的劝你不要这样做。XML
是一种上下文语言,而正则表达式不是。正则表达式根本无法正确解析 XML 结果。
最好的情况是,您得到了一个 hack,只有在 XML 保持相同格式的情况下才有效。但正如 XML 规范所说,格式可以偶然并保留相同的语义,这是一个危险的假设,并且会产生脆弱的代码。
我知道你有理由想要这样做——你已经有了一个答案,为你提供了一种方法。我建议解析器仍然是正确的回答。
但是使用 XML 解析器,您会得到xpath
- 这很像正则表达式,但适用于分层信息。
像这样的东西:
#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
my $twig = XML::Twig -> parse ( \*DATA );
my $version = $twig -> get_xpath('//item/artifactId[string()="myproject"]/../version',0)->text;
print $version;
__DATA__
<xml>
<item>
<artifactId>myproject</artifactId>
<version>1.14.0-SNAPSHOT</version>
</item>
</xml>
希望您能看到它xpath
是如何工作的?//item
在结构内的任何位置查找项目。[string()=
查询文本内容。您可以执行类似[@someAtt="fish"]
检查属性之类的操作。
然后我们..
向上 ( item
) 并获取version
元素。然后获取text
值。
作为单行者:
perl -MXML::Twig -0777 -e 'print XML::Twig -> parse ( <> ) -> get_xpath('/item/artifactId[string()="myproject"]/../version',0)->text,"\n" yourxmlfile.xml
现在,我建议是XML::Twig
因为我认为它更容易学习。XML::LibXML
也相当不错。
但它在 Windows 上与 Strawberry Perl 一起分发,并且可以在许多包管理器中轻松使用 - 或者从CPAN
.
或者 -xmlstarlet
应该允许你做同样的事情。