Localiza um padrão específico em um arquivo de texto e os exclui da saída?

1

Eu tenho um arquivo com cerca de 25 mil linhas. Dê uma olhada na minha entrada de amostra e na saída necessária

ENTRADA:

zone name tommy
* pwwn xxxxxxxx
  pwwn xyzabcda
* pwwn xcvuytnm
zone name sammy
* pwwn akslapsl
* pwwn dfgsjasl
* pwwn xcvuytnm
zone name angelfalls
* pwwn xxxxxxxx
  pwwn xyzabcda
zone name Newyork
* pwwn xxxxxxxx
  pwwn xyzabcda

Saída desejada:

zone name tommy
* pwwn xxxxxxxx
  pwwn xyzabcda
* pwwn xcvuytnm
zone name angelfalls
* pwwn xxxxxxxx
  pwwn xyzabcda
zone name Newyork
* pwwn xxxxxxxx
  pwwn xyzabcda

Eu quero que a saída exclua todas as zonas que contêm um * em todas as linhas antes do pwwn. No meu exemplo, sammy nome da zona tem um * em todas as três linhas pwwn, portanto eu excluí todas as linhas * sob o nome da zona sammy.

Usando o Solaris 5.10, Korn Shell.

    
por ayrton_senna 20.02.2018 / 19:37

3 respostas

3

Awk solução:

awk '/^zone /{ 
         if (f) print r;
         r = $0; f = 0; next 
     }
     { r = r ORS $0; if (/^[^*]* pwwn/) f = 1; }
     END{ if (f) print r }' file

A saída:

zone name tommy
* pwwn xxxxxxxx
  pwwn xyzabcda
* pwwn xcvuytnm
zone name angelfalls
* pwwn xxxxxxxx
  pwwn xyzabcda
zone name Newyork
* pwwn xxxxxxxx
  pwwn xyzabcda
    
por 20.02.2018 / 19:53
0

Veja como eu faria isso como um pipeline rápido de perl:

perl -p00e 's/\nzone/\n\nzone/g' inputfile \
| perl -n00e '$t = $_; s/^\*.*?\n//mg; print $t if /pwwn/' \
| perl -p00e 's/\n\n/\n/'

A primeira linha adiciona uma linha em branco entre cada registro. A segunda linha itera sobre cada registro, verificando se restam pwwn linhas depois de remover todas as linhas que começam com * dentro desse registro - e, nesse caso, imprime esse registro. A terceira linha remove as linhas em branco que separam cada registro.

    
por 20.02.2018 / 19:58
0
$ awk -v RS='(^|\n)zone' '/\n[^*]/ { print "zone" $0 }' input 
zone name tommy
* pwwn xxxxxxxx
  pwwn xyzabcda
* pwwn xcvuytnm
zone name angelfalls
* pwwn xxxxxxxx
  pwwn xyzabcda
zone name Newyork
* pwwn xxxxxxxx
  pwwn xyzabcda

Este script awk define o Separador de Registros ( RS ) como o início do arquivo de entrada ou uma nova linha, seguido pela palavra "zona". Em seguida, imprime cada "registro" que contém pelo menos uma nova linha não seguida por * .

Ele precisa imprimir a palavra "zone" junto com $0 porque awk automaticamente remove o RS de cada registro de entrada.

NOTA: Como RS não é apenas uma nova linha por si só, $0 contém as novas linhas no final de cada linha de entrada (isso está intimamente relacionado ao motivo mencionado acima para saber por que a "zona" precisa ser impresso). Isso significa que haverá uma linha extra em branco no final da saída. Se isso for um problema, a maneira mais fácil de se livrar dele é com sed . por exemplo,

awk -v RS='(^|\n)zone' '/\n[^*]/ { print "zone" $0 }' input | sed '$d'

Por fim, se o pwwn for uma parte importante dos critérios de correspondência, altere a correspondência de expressão regular no script de /\n[^*]/ para /\n[^*] pwwn/ . (com a entrada de exemplo fornecida, a saída é idêntica, mas pode diferir com sua entrada real muito maior)

    
por 21.02.2018 / 04:41