Imprime linhas alternadas com condicional

3

Ainda lutando com arquivos de log confusos. O que eu quero é encontrar linhas que coincidam primeiro com a string X e depois com a string Y. Eu então quero imprimi-las juntas. O problema é que, às vezes, há X, mas não Y.

Exemplo de entrada

31 X
32 Y
33 X
34 Y
35 X
36 X
37 Y
38 X
39 X

Saída esperada

31 X
32 Y
33 X
34 Y
36 X
37 Y

Assim, as linhas 35, 38 e 39 são omitidas porque não há nenhuma string Y.

Meu ponto de partida é o seguinte:

cat $filename | grep -E X\|Y | grep -A1 'X'

Mas isso não filtra as linhas 35, 38 e 39. O que eu quero é uma condição: apenas imprima as linhas X e Y se houver Y. Se não, não imprima nada.

    
por Rogier Visser 02.07.2015 / 21:58

4 respostas

2

Se eu entendi corretamente, você só quer linhas contendo X se elas forem seguidas por uma linha contendo Y, e então você quer as duas linhas.

grep -A1 X filename |grep --no-group-separator -B1 Y

    
por 02.07.2015 / 22:58
4

Usando sed :

sed -n ':b /X/ { h; n; /Y/! b b; H; x; p; }'

Saída:

31 X
32 Y
33 X
34 Y
36 X
37 Y
    
por 03.07.2015 / 08:28
3

Outro sed :

$ sed -e '/X/{
    $!N
    /\n.*Y/!D
}' file
31 X
32 Y
33 X
34 Y
36 X
37 Y
    
por 03.07.2015 / 08:37
3

Existem várias ferramentas que podem fazer isso. Se você tem pcregrep (deve estar disponível no repositório de sua distribuição), você pode fazer:

$ pcregrep -M 'X\n[^\n]+Y' file 
31 X
32 Y
33 X
34 Y
36 X
37 Y

A opção -M permite que o padrão corresponda a todos os caracteres de nova linha e a expressão regular corresponda a um X , seguido por uma nova linha e, em seguida, todos os caracteres não pertencentes à nova linha e Y .

Outra opção é escrever um pequeno script que salve a linha anterior se ela corresponder a X e imprimi-la junto com a atual se a linha atual corresponder a Y . Por exemplo, em awk :

$ awk '{if(last~/X/ && /Y/){print last"\n"$0}last=$0}' file 
31 X
32 Y
33 X
34 Y
36 X
37 Y

Ou Perl:

$ perl -ne '$last=~/X/ && /Y/ && print "$last$_"; $last=$_' file 
31 X
32 Y
33 X
34 Y
36 X
37 Y
    
por 03.07.2015 / 01:04