В общем, вы не . Синтаксический анализ XML / HTML достаточно сложен, если вы не пытаетесь сделать это кратко, и, хотя вы сможете взломать решение, которое успешно работает с ограниченным подмножеством XML, в конечном итоге оно сломается.
Кроме того, есть много замечательных языков с отличными синтаксическими анализаторами XML, уже написанными , так почему бы не использовать один из них и сделать вашу жизнь проще?
Я не знаю, есть ли парсер XML, созданный для awk, но я боюсь, что если вы захотите проанализировать XML с помощью awk, вы получите много "молотков для гвоздей, отвертки для винтов "ответы. Я уверен, что это можно сделать, но вам, вероятно, будет проще написать что-нибудь быстрое в 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'
.