как извлечь значение из строки в xml с помощью grep или awk в Linux

У меня есть файл, содержащий:

DEVICE="7" PGMNR="24" VCONF="800" 

В этом файле я хочу найти PGMNR="24" и мне нужно значение 24 без " .

PGMNR="24" может быть расположен в любом месте линии. Начало, середина или конец строки.

Я не могу понять, как получить значение.

XML Пример из комментариев:

 <?xml version="1.0" encoding="utf-8"?> <NT3Config> <System Dev="7" PGMNR="24" VCONF="800 800" /> <WA-NT info="23 1 1 1 61 17 00" name="Soja T#1" /> <WA-NT info="23 2 2 1 61 17 00" name="MatadorM" /> <SCALE AdNr="0" Calib="0 0 0 0 0 0" Setting="0 0 0 0 0 0 0" /> <SCALE AdNr="1" Calib="0 0 0 0 0 0" Setting="0 0 0 0 0 0 0" /> <SCALE AdNr="2" Calib="0 0 0 0 0 0" Setting="0 0 0 0 0 0 0" /> <GSM PIN="" PORT="0" TLF="" /> </NT3Config> 

Я уже ответил на это с помощью парсера – что я считаю «правильным путем».

Это был бы «неправильный путь», но должен был сделать трюк с минимальным количеством инструментов POSIX:

 grep PGMNR $filename | sed -e 's/.*PGMNR=\"//' -e 's/\".*//' 

Вы можете использовать grep с PCRE ( -P ):

 grep -Po 'PGMNR=\"\K[^"]+(?=\")' file.txt 
  • PGMNR=\" будет соответствовать части PGMNR=" , \K PGMNR=" совпадение

  • [^"]+ будет содержать номер

  • Положительный обратный шаблон с нулевой шириной (?=\") Будет следить за тем, чтобы за номером последовал символ " .

Пожалуйста, не надо. XML не очень хорошо работает с регулярными выражениями и синтаксическим анализом на основе строк, потому что в XML есть множество вещей, которые семантически идентичны, но имеют разные «совпадения шаблонов».

С помощью xmlstarlet вы можете извлечь выражение xpath которое даст вам ваше значение.

Или мой любимый использует perl и XML::Twig для анализа вашего XML, и снова – получите значение, которое вы хотите таким образом.

 #!/usr/bin/env perl use strict; use warnings; use XML::Twig; my $twig = XML::Twig -> new ( 'pretty_print' => 'indented_a' ) -> parse ( \*DATA ); print "PGMNR: ", $twig -> get_xpath('//System',0) -> att('PGMNR'),"\n"; __DATA__ <?xml version="1.0" encoding="utf-8"?> <NT3Config> <System Dev="7" PGMNR="24" VCONF="800 800" /> <WA-NT name="Soja T#1" info="23 1 1 1 61 17 00" /> <WA-NT name="MatadorM" info="23 2 2 1 61 17 00" /> <SCALE AdNr="0" Setting="0 0 0 0 0 0 0" Calib="0 0 0 0 0 0" /> <SCALE AdNr="1" Setting="0 0 0 0 0 0 0" Calib="0 0 0 0 0 0" /> <SCALE AdNr="2" Setting="0 0 0 0 0 0 0" Calib="0 0 0 0 0 0" /> <GSM TLF="" PIN="" PORT="0" /> </NT3Config> 

Это может «один лайнер», если это необходимо, или вы можете xmlstarlet что XPATH.

 perl -0777 -MXML::Twig -e 'print XML::Twig -> parse ( <> )-> get_xpath('//System',0) -> att('PGMNR');' 

Примечание. Причина, по которой я яростно против синтаксического анализа на основе регулярных выражений, заключается в том, что все это полностью допустимые способы представления вашего XML:

 <?xml version="1.0" encoding="utf-8"?> <NT3Config> <System Dev="7" PGMNR="24" VCONF="800 800" /> <WA-NT info="23 1 1 1 61 17 00" name="Soja T#1" /> <WA-NT info="23 2 2 1 61 17 00" name="MatadorM" /> <SCALE AdNr="0" Calib="0 0 0 0 0 0" Setting="0 0 0 0 0 0 0" /> <SCALE AdNr="1" Calib="0 0 0 0 0 0" Setting="0 0 0 0 0 0 0" /> <SCALE AdNr="2" Calib="0 0 0 0 0 0" Setting="0 0 0 0 0 0 0" /> <GSM PIN="" PORT="0" TLF="" /> </NT3Config> 

И это:

 <?xml version="1.0" encoding="utf-8"?> <NT3Config ><System Dev="7" PGMNR="24" VCONF="800 800" /><WA-NT info="23 1 1 1 61 17 00" name="Soja T#1" /><WA-NT info="23 2 2 1 61 17 00" name="MatadorM" /><SCALE AdNr="0" Calib="0 0 0 0 0 0" Setting="0 0 0 0 0 0 0" /><SCALE AdNr="1" Calib="0 0 0 0 0 0" Setting="0 0 0 0 0 0 0" /><SCALE AdNr="2" Calib="0 0 0 0 0 0" Setting="0 0 0 0 0 0 0" /><GSM PIN="" PORT="0" TLF="" /></NT3Config> 

И это:

 <?xml version="1.0" encoding="utf-8"?> <NT3Config><System Dev="7" PGMNR="24" VCONF="800 800"/><WA-NT info="23 1 1 1 61 17 00" name="Soja T#1"/><WA-NT info="23 2 2 1 61 17 00" name="MatadorM"/><SCALE AdNr="0" Calib="0 0 0 0 0 0" Setting="0 0 0 0 0 0 0"/><SCALE AdNr="1" Calib="0 0 0 0 0 0" Setting="0 0 0 0 0 0 0"/><SCALE AdNr="2" Calib="0 0 0 0 0 0" Setting="0 0 0 0 0 0 0"/><GSM PIN="" PORT="0" TLF=""/></NT3Config> 

И это:

 <?xml version="1.0" encoding="utf-8"?> <NT3Config> <System Dev="7" PGMNR="24" VCONF="800 800"/> <WA-NT info="23 1 1 1 61 17 00" name="Soja T#1"/> <WA-NT info="23 2 2 1 61 17 00" name="MatadorM"/> <SCALE AdNr="0" Calib="0 0 0 0 0 0" Setting="0 0 0 0 0 0 0"/> <SCALE AdNr="1" Calib="0 0 0 0 0 0" Setting="0 0 0 0 0 0 0"/> <SCALE AdNr="2" Calib="0 0 0 0 0 0" Setting="0 0 0 0 0 0 0"/> <GSM PIN="" PORT="0" TLF=""/> </NT3Config> 

И вы даже можете столкнуться с некоторыми вашими унарными тегами, как указано выше, явно закрытыми:

 <System Dev="7" PGMNR="24" VCONF="800 800"/> 

А также:

 <System Dev="7" PGMNR="24" VCONF="800 800"></System> 

Оба говорят то же самое, что касается XML.

ЖЕСТКО из-за дополнительного ограничения заблокированной системы, вот действительно грязный способ сделать это – но обратите внимание на предостережения выше – мы больше не разбираемся в XML, мы делаем простой текст, и он может очень легко сломаться. (Хрупкий код заставляет ваших системных администраторов печально).

 #!/usr/bin/env perl use strict; use warnings; local $/; my ( $PGMNR ) = <DATA> =~ m/PGMNR=\"(\d+)\"/; print $PGMNR; __DATA__ <?xml version="1.0" encoding="utf-8"?> <NT3Config> <System Dev="7" PGMNR="24" VCONF="800 800" /> <WA-NT name="Soja T#1" info="23 1 1 1 61 17 00" /> <WA-NT name="MatadorM" info="23 2 2 1 61 17 00" /> <SCALE AdNr="0" Setting="0 0 0 0 0 0 0" Calib="0 0 0 0 0 0" /> <SCALE AdNr="1" Setting="0 0 0 0 0 0 0" Calib="0 0 0 0 0 0" /> <SCALE AdNr="2" Setting="0 0 0 0 0 0 0" Calib="0 0 0 0 0 0" /> <GSM TLF="" PIN="" PORT="0" /> </NT3Config> 

Или onelinering в perl:

 perl -0777 -e 'print <> =~ m/PGMNR=\"(\d+)\"/;'