我有一个具有以下数据格式的 XML 文件:
<net NetName="abc" attr1="123" attr2="234" attr3="345".../>
<net NetName="cde" attr1="456" attr2="567" attr3="678".../>
....
谁能告诉我如何使用 awk one-liner 对 XML 文件进行数据挖掘?比如我想知道abc的attr3。它将返回 345 给我。
一般来说,你不会。如果不尝试简洁地进行 XML/HTML 解析就已经够难了,虽然您可能能够拼凑出一个使用有限的 XML 子集成功的解决方案,但最终它会失败。
此外,已经编写了许多具有出色 XML 解析器的出色语言,那么为什么不使用其中一种来让您的生活更轻松呢?
我不知道是否有为 awk 构建的 XML 解析器,但我担心如果你想用 awk 解析 XML,你会得到很多“锤子是用来钉子的,螺丝刀是用来螺丝钉的”答案。我确信它可以完成,但是用 Perl 快速编写一些使用 XML::Simple(我个人最喜欢的)或其他一些 XML 解析模块的东西可能会更容易。
为了完整起见,我想指出,如果您的代码段是整个文件的示例,则它不是有效的 XML。有效的 XML 应该具有开始和结束标记,如下所示:
<netlist>
<net NetName="abc" attr1="123" attr2="234" attr3="345".../>
<net NetName="cde" attr1="456" attr2="567" attr3="678".../>
....
</netlist>
我确信无效的 XML 有它的用途,但是一些 XML 解析器可能会抱怨它,所以除非你死心塌地地使用 awk 单线器来尝试半屁股“解析”你的“XML”,否则你可能想要考虑使您的 XML 有效。
作为对您的编辑的回应,我仍然不会将其作为单行符,但这是您可以使用的 Perl 脚本:
#!/usr/bin/perl
use strict;
use warnings;
use XML::Simple;
sub usage {
die "Usage: $0 [NetName] ([attr])\n";
}
my $file = XMLin("file.xml", KeyAttr => { net => 'NetName' });
usage() if @ARGV == 0;
exists $file->{net}{$ARGV[0]}
or die "$ARGV[0] does not exist.\n";
if(@ARGV == 2) {
exists $file->{net}{$ARGV[0]}{$ARGV[1]}
or die "NetName $ARGV[0] does not have attribute $ARGV[1].\n";
print "$file->{net}{$ARGV[0]}{$ARGV[1]}.\n";
} elsif(@ARGV == 1) {
print "$ARGV[0]:\n";
print " $_ = $file->{net}{$ARGV[0]}{$_}\n"
for keys %{ $file->{net}{$ARGV[0]} };
} else {
usage();
}
使用 1 或 2 个参数从命令行运行此脚本。第一个参数是'NetName'
你要查找的,第二个是你要查找的属性。如果没有给出属性,它应该只列出该的所有属性'NetName'
。
我编写了一个xml_grep2
基于XML::LibXML的工具,它是libxml2的 perl 接口。
你会通过这样做找到你正在寻找的价值:
xml_grep2 -t '//net[@NetName="abc"]/@attr3' to_grep.xml
xmlgawk 可以非常轻松地使用 XML。
$ xgawk -lxml 'XMLATTR["NetName"]=="abc"{print XMLATTR["attr3"]}' test.xml
这一个班轮可以解析 XML 并打印“345”。
如果你没有 xmlgawk 并且你的 XML 格式是固定的,那么普通的 awk 就可以了。
$ nawk -F '[ ="]+' '/abc/{for(i=1;i<=NF;i++){if($i=="attr3"){print $(i+1)}}}' test.xml
该脚本可以返回“345”。但我认为这是非常危险的,因为普通的 awk 不能使用 XML。
你可以试试这个漂亮的小脚本:http ://awk.info/?doc/tools/xmlparse.html