awk começando de um texto fixo, até a primeira linha em branco

awk começando de um texto fixo, até a primeira linha em branco

Estou tentando entrar em algo que retornará apenas o primeiro "parágrafo" ou "seção" separado por uma linha em branco. Achei que poderia usar awkor sedpara obter um intervalo de acordo com outras respostas, mas não parece funcionar.

$ cat txt
Package: plasma-desktop
Architecture: amd64
Version: 4:5.12.9.1-0ubuntu0.1
Supported: 3y

Package: plasma-desktop
Architecture: amd64
Version: 4:5.12.4-0ubuntu1
Supported: 3y

$ cat txt |awk '/^Package:/,/^$/'
Package: plasma-desktop
Architecture: amd64
Version: 4:5.12.9.1-0ubuntu0.1
Supported: 3y

Package: plasma-desktop
Architecture: amd64
Version: 4:5.12.4-0ubuntu1
Supported: 3y

Não deveria retornar apenas a primeira "seção"? (conforme: Grep começando de um texto fixo, até a primeira linha em branco e https://www.unix.com/shell-programming-and-scripting/148692-awk-script-match-pattern-till-blank-line.html)

  • Se eu usar grep -ve ^$as linhas em branco serão removidas, então não há caracteres especiais.
  • Se eu tentar extrair uma parte diferente, obtenho as partes de ambas as "seções":

    $ cat txt |awk '/^Package:/,/^Version:/'
    Package: plasma-desktop
    Architecture: amd64
    Version: 4:5.12.9.1-0ubuntu0.1
    Package: plasma-desktop
    Architecture: amd64
    Version: 4:5.12.4-0ubuntu1
    
  • Se eu usar sed -n '/^Package:/,/^$/p'ou sed -n '/^Package:/,/^Version:/p'obtiver os mesmos resultados que o equivalente awk.

Como faço para obter awkou sedparar após a primeira ocorrência?

Responder1

É exatamente por isso que o awk tem um modo de parágrafo:

$ awk -v RS= 'NR==1' file
Package: plasma-desktop
Architecture: amd64
Version: 4:5.12.9.1-0ubuntu0.1
Supported: 3y

e imprimir o segundo registro é apenas a mudança óbvia de NR==1para NR==2:

$ awk -v RS= 'NR==2' file
Package: plasma-desktop
Architecture: amd64
Version: 4:5.12.4-0ubuntu1
Supported: 3y

Nunca use expressões de intervalo - elas tornam o código para problemas triviais um pouco mais breve do que usar um sinalizador, mas se seus requisitos mudarem um pouco, será necessária uma reescrita completa ou condições duplicadas. Então, sempre que você quiser usar /begin/,/end/com sed ou awk, use /begin/{f=1} f{print} /end/{f=0}com awk e isso lhe dará MUITO mais controle sobre quando/como imprimir as linhas de início/fim, etc.

Responder2

No /begin/,/end/, os "sinalizadores de ação" são ativados sempre que uma /begin/correspondência é encontrada e desativados quando /end/a correspondência é encontrada. As linhas de limite com “início” e “fim” também são impressas.

As consequências para sua entrada são (as linhas impressas têm um comentário depois delas nos exemplos abaixo):

  • Com '/^Package:/,/^$/':
    Package: plasma-desktop        #TURN ON
    Architecture: amd64            #
    Version: 4:5.12.9.1-0ubuntu0.1 #
    Supported: 3y                  #
                                   #TURN OFF
    Package: plasma-desktop        #TURN ON
    Architecture: amd64            #
    Version: 4:5.12.4-0ubuntu1     #
    Supported: 3y                  #
  • Com '/^Package:/,/^Version:/':
    Package: plasma-desktop        #TURN ON
    Architecture: amd64            #
    Version: 4:5.12.9.1-0ubuntu0.1 #TURN OFF
    Supported: 3y

    Package: plasma-desktop        #TURN ON
    Architecture: amd64            #
    Version: 4:5.12.4-0ubuntu1     #TURN OFF
    Supported: 3y

Para imprimir apenas o parágrafo começando em "Pacote:" você pode escrever

sed -ne '/^$/q' -e '/^Package:/,$p' file

sedencerra o processamento do arquivo assim que encontra uma linha em branco por causa de /^$/q.

Com awk:

awk '/^$/{exit};/^Package:/,0' file

Responder3

Como comentado porQuasímodo

/begin/,/end/obtém linhas que correspondem a essas expressões regulares, incluindo as linhas de limite. start liga a impressão e end desliga. A linha logo após a sua linha em branco ativa a impressão novamente, pois também contém Package:.

Percebi que posso usar sede alterar o /begin/to 0e ele começará do início. Como há apenas um começo, ele corresponderá apenas uma vez.

$ cat txt |sed -n '0,/^$/p'
Package: plasma-desktop
Architecture: amd64
Version: 4:5.12.9.1-0ubuntu0.1
Supported: 3y

informação relacionada