A impressão varia desde a última ocorrência de um determinado padrão até a primeira ocorrência de outro padrão

A impressão varia desde a última ocorrência de um determinado padrão até a primeira ocorrência de outro padrão

Bom dia, isso é extremamente parecido com a perguntaGrep da última ocorrência de um padrão para outro padrão(vários meses), acrescentando um pouco mais de detalhes.

Estou tentando escrever um script UNIX para um arquivo com vários padrões duplicados, seguido pelo padrão que estou procurando. No entanto, não tenho 'tac' ou 'tail -r' (usando o emulador UNIX, MKS Toolkit) e estou procurando retornar a última ocorrência de Pattern1 antes de Pattern2, seguida pelos dados entre Pattern1 e Pattern2 e, em seguida, Pattern2 também. Os padrões neste caso seriam 'Condição 1' e 'Condição 2':

saída.out:

...
Condition 1: A
data1
Condition 1: B
data2
Condition 2: C
data3
Condition 1: D
data4
Condition 1: E
data5
Condition 2: F
...

Eu gostaria de escrever um script awk (ou sed, mas imaginei que awk seria a ferramenta certa) para retornar:

Condition 1: B
data2
Condition 2: C
Condition 1: E
data5
Condition 2: F

Acho que é alguma forma da linha abaixo, mas não consigo acertar a sintaxe:

awk '/Condition 1/ {acc = $0;} /,/Condition 2/ {print ?}' output.out

Trabalhar em '/,/' é onde parece que estou tendo problemas. Queria saber se alguém tivesse algum conselho, ficaria muito grato. Muito obrigado por qualquer ajuda e tempo relacionado a esta questão.

Responder1

Tentar:

$ awk 'f{a=a"\n"$0} /Condition 1/{a=$0; f=1} f && /Condition 2/{print a; f=0}' output.out 
Condition 1: B
data2
Condition 2: C
Condition 1: E
data5
Condition 2: F

Como funciona

  • f{a=a"\n"$0}

    Se a variável ffor verdadeira (diferente de zero), anexe a linha atual ao final da variável a.

  • /Condition 1/{a=$0; f=1}

    Se a linha atual contiver Condition 1, defina spara a linha atual e defina a variável fcomo 1.

  • f && /Condition 2/{print a; f=0}

    Se ffor verdadeiro e a linha atual contiver Condition 2, imprima a variável ae fvolte para zero.

Responder2

Quando você quiser endereçamento reverso no processamento de texto, useex

Isso éPOSIX especificado, e é a forma programável de vi(e viantecessor imediato de) - muito flexível.

printf '%s\n' 'g/Condition 2/?Condition 1?,.p' | ex output.out

Isso significa:

Para cada linha ( globalmente) que corresponda ao padrão "Condição 2", pesquise para trás a instância imediatamente anterior de "Condição 1" e pimprima todas as linhas dessa linha para a linha atual ( .) (que é a linha com "Condição 2" em isto).

A saída da entrada fornecida é exatamente como você descreve.

Responder3

sed 'H;/PATTERN_1/h;/PATTERN_2/!d;x' infile

embora isso presuma que qualquer linha correspondente PATTERN_2seja precedida por pelo menos uma linha correspondente PATTERN_1. Para o caso mais geral, adicione outra condição para testar a PATTERN_1presença no espaço do padrão antes de imprimir:

sed 'H;/PATTERN_1/h;/PATTERN_2/!d;x;/PATTERN_1/!d' infile

Responder4

Aqui está um pedaço maligno de perl:

perl -0777 -ne '
    my $c1 = qr/Condition 1/;
    my $c2 = qr/Condition 2/;
    print for map {s/$c2.*?\n\K.*//s; $_}
              grep {/$c2/}
              split /(?=$c1)/ms;
' output.out

Isto:

  • lê o arquivo inteiro (usando as opções -0777e -n),
  • divide onde a Condição 1 aparece ( split),
  • filtra parágrafos onde a Condição 2 não aparece ( grep),
  • em seguida, remove de cada parágrafo interessante todas as linhas que seguem a linha da Condição 2 ( map).

informação relacionada