como extrair um valor de uma string em xml usando grep ou awk no Linux

1

Eu tenho um arquivo contendo:

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

Neste arquivo, quero encontrar PGMNR="24" e preciso do valor 24 sem o " .

O PGMNR="24" pode estar localizado em qualquer lugar na linha. O começo, meio ou no final da linha.

Eu não consigo descobrir como obter o valor.

XML Amostra dos comentários:

<?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>
    
por Søren Bonefeld 15.09.2015 / 17:11

3 respostas

1

Já respondi usando um analisador - o que considero o "caminho certo".

Este seria o "caminho errado", mas deve fazer o truque com a quantidade mínima de ferramentas POSIX:

grep PGMNR $filename | sed -e 's/.*PGMNR=\"//' -e 's/\".*//'
    
por 15.09.2015 / 18:10
2

Você pode usar grep com PCRE ( -P ):

grep -Po 'PGMNR=\"\K[^"]+(?=\")' file.txt
  • PGMNR=\" corresponderá à parte PGMNR=" , \K descartará a correspondência

  • [^"]+ conterá o número

  • O padrão lookahead positivo de largura zero (?=\") garante que o número seja seguido por " .

por 15.09.2015 / 17:18
1

Por favor - não faça. XML não funciona bem com expressões regulares e análise baseada em linha, porque há um monte de coisas que você pode fazer em XML que são semanticamente idênticas, mas com diferentes 'combinações de padrões'.

Com xmlstarlet você pode extrair uma expressão xpath que lhe dará o seu valor.

Ou meu favorito é usar perl e XML::Twig para analisar seu XML e, novamente, obter o valor desejado dessa maneira.

#!/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>

Isso pode 'um forro' se for necessário, ou você pode xmlstarlet desse XPATH.

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

Nota - a razão pela qual eu sou veementemente contra a análise baseada em expressões regulares é porque estas são todas formas completamente válidas de apresentar o seu 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>

E isso:

<?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>

E isso:

<?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>

E isso:

<?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>

E você pode até mesmo encontrar algumas de suas tags unárias, conforme explicado acima:

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

E:

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

Ambos estão dizendo a mesma coisa, no que diz respeito ao XML.

PURELY por causa da restrição adicional de um sistema bloqueado, aqui está a maneira realmente imunda de fazê-lo - mas observe as advertências acima - não estamos analisando XML mais, estamos fazendo texto simples, e ele pode quebrar muito facilmente. (Código frágil faz seus administradores tristes).

#!/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>

Ou onelinering em perl:

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