Comando Awk para obter a próxima linha do padrão correspondente e cortar a cadeia entre dois padrões

0

Eu preciso obter a próxima linha após o padrão correspondente e preciso cortar ou cortar o valor entre dois padrões dessa linha.

Exemplo de arquivo de origem

<h2>Commodity Information</h2>

<dl>
        <dt>Commodity Orgin</dt>
        <dd>uerb45e001.material.com</dd>

        <dt>Commodity Code & Dimension</dt>
        <dd>151151.15 Dim 90 </dd>

        <dt>Commodity Serial #</dt>
        <dd>2009081020</dd>

        <dt>Client Name</dt>
        <dd>Jack</dd>

</dl>

Saída desejada:

Commodity Orgin : uerb45e001.material.com
Commodity Code & Dimension : 151151.15 Dim 90
Commodity Serial # : 2009081020
Client Name : Jack
    
por ramp 09.06.2016 / 08:01

3 respostas

2

lynx -dump para converter o HTML em texto sem formatação e awk para reformatar a saída, definindo o separador de campo para uma nova linha ( \n ) e o separador de registro para duas ou mais linhas novas ( \n\n+ ).

A função sub() chama no script awk a remoção de espaços em excesso antes de imprimir a saída necessária.

$ lynx -dump ramp.html | 
    awk -v RS='\n\n' -F'\n' '/^[[:space:]]+/ {
        sub(/^ +/,"",$1);
        sub(/ +/," ",$2);
        print $1":"$2
    }'
Commodity Orgin: uerb45e001.material.com
Commodity Code & Dimension: 151151.15 Dim 90
Commodity Serial #: 2009081020
Client Name: Jack

Eu realmente não gosto de fazer isso porque nunca é uma boa ideia analisar XML ou HTML com expressões regulares . não funciona . Mesmo que você consiga ativá-lo de modo que pareça funcionar, ele é extremamente frágil e WILL quebra assim que o HTML ou XML muda o suficiente do que seus regexps estão procurando. Um analisador XML ou HTML real é a única coisa somente que pode fazer o trabalho corretamente.

Mas, com isso dito, aqui está algo que usa apenas sed e fmt , ferramentas que devem estar disponíveis em qualquer sistema semelhante a um unix:

$ sed -e '/<d[td]\|^[[:blank:]]*$/!d
          s/<[^>]*>//g;
          s/^ *//;
          /^\(Commodity\|Client\)/ s/$/:/' ramp.html | 
      fmt |
      sed -e '/^[[:blank:]]*$/d'
Commodity Orgin: uerb45e001.material.com
Commodity Code & Dimension: 151151.15 Dim 90
Commodity Serial #: 2009081020
Client Name: Jack

O primeiro script sed exclui todas as linhas exceto linhas e linhas em branco contendo uma tag <DT> ou <DD> , depois remove todas as tags HTML da entrada, exclui espaços à esquerda e adiciona um : ao final das linhas do nome do campo. A saída de sed é então canalizada para fmt para reformatar as linhas, depois para sed novamente para excluir linhas em branco.

Isso é um hack e só é garantido que funcione exatamente na entrada de amostra que você forneceu. Qualquer coisa substancialmente diferente é susceptível de quebrar o roteiro. É o que acontece quando você usa expressões regulares para analisar qualquer HTML, exceto o mais trivial, ou XML.

    
por 09.06.2016 / 09:11
0

Se você tivesse xmlstarlet e a entrada fosse (massageada em) XML válido, poderia fazer algo assim:

xmlstarlet sel --text -t -m //dt -v 'concat(., " : ", following::dd)' -nl input.html
    
por 09.06.2016 / 14:35
0
paste -d: <(grep -oP '<dt>\K.*(?=<)' file.html) <(grep -oP '<dd>\K.*(?=<)' file.html) | sed 's/:/ : /'

Commodity Orgin : uerb45e001.material.com
Commodity Code & Dimension : 151151.15 Dim 90 
Commodity Serial # : 2009081020
Client Name : Jack
  • dois comandos grep para extrair texto entre as tags <dt> e <dd> (supondo que estejam na mesma linha, conforme determinado no arquivo de amostra do OP
  • paste combina os dois arquivos linha por linha com : como separador
  • O comando sed substitui o separador ':' por ':' conforme a saída esperada do OP (este hack não funcionará se o texto entre as tags também contiver o caractere:)
  • Veja esta resposta para obter explicações sobre o uso de \K e (?=)
por 09.06.2016 / 16:13