3

我有一个具有以下数据格式的 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 给我。

4

5 回答 5

7

一般来说,你不会。如果不尝试简洁地进行 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'

于 2009-05-26T05:47:28.993 回答
7

我编写了一个xml_grep2基于XML::LibXML的工具,它是libxml2的 perl 接口。

你会通过这样做找到你正在寻找的价值:

xml_grep2 -t '//net[@NetName="abc"]/@attr3' to_grep.xml

该工具可以在http://xmltwig.com/tool/找到

于 2009-05-26T07:23:43.103 回答
5

xmlgawk 可以非常轻松地使用 XML。

$ xgawk -lxml 'XMLATTR["NetName"]=="abc"{print XMLATTR["attr3"]}' test.xml

这一个班轮可以解析 XML 并打印“345”。

于 2009-05-26T12:53:00.973 回答
2

如果你没有 xmlgawk 并且你的 XML 格式是固定的,那么普通的 awk 就可以了。

$ nawk -F '[ ="]+' '/abc/{for(i=1;i<=NF;i++){if($i=="attr3"){print $(i+1)}}}' test.xml

该脚本可以返回“345”。但我认为这是非常危险的,因为普通的 awk 不能使用 XML。

于 2009-05-26T13:16:07.277 回答
0

你可以试试这个漂亮的小脚本:http ://awk.info/?doc/tools/xmlparse.html

于 2013-10-29T19:33:42.230 回答