Imprimir linha de correspondência e enésima linha da linha correspondente

17

Estou tentando imprimir a linha correspondente e a quarta linha da linha correspondente (linha que contém a expressão que estou procurando).

Eu tenho usado o seguinte código: sed -n 's/^[ \t]*//; /img class=\"devil_icon/,4p' input.txt

Mas isso só imprime a linha correspondente.

Isto imprime apenas a quarta linha. awk 'c&&!--c;/img class=\"devil_icon/{c=4}' input.txt

Eu preciso imprimir tanto a linha correspondente quanto a quarta linha.

    
por debal 24.08.2013 / 12:43

5 respostas

18

No awk, você faria da seguinte maneira

awk '/pattern/{nr[NR]; nr[NR+4]}; NR in nr' file > new_file'

ou

awk '/pattern/{print; nr[NR+4]; next}; NR in nr' file > new_file'

Explicação

A primeira solução encontra todas as linhas que correspondem a pattern . Quando encontra uma correspondência, armazena o número do registro ( NR ) na matriz nr . Também armazena o 4º registro de NR no mesmo array. Isso é feito pelo nr[NR+4] . Cada registro ( NR ) é então verificado para ver se está presente na matriz nr , em caso afirmativo, o registro é impresso.

A segunda solução funciona essencialmente da mesma maneira, exceto quando encontra o pattern que imprime a linha e, em seguida, armazena o 4º registro à frente no array nr , e então vai para o próximo registro. Então, quando awk encontrar este 4º registro, o NR in nr bloco será executado e imprimirá este registro +4 depois.

Exemplo

Veja um exemplo de arquivo de dados, sample.txt .

$ cat sample.txt 
1
2
3
4 blah
5
6
7
8
9
10 blah
11
12
13
14
15
16

Usando a primeira solução:

$ awk '/blah/{nr[NR]; nr[NR+4]}; NR in nr' sample.txt 
4 blah
8
10 blah
14

Usando a segunda solução:

$ awk '/blah/{print; nr[NR+4]; next}; NR in nr' sample.txt 
4 blah
8
10 blah
14
    
por 24.08.2013 / 14:45
4
sed -n 's/^[ \t]*/; /img class=\"devil_icon/,+4 { 3,5d ; p }' input.txt

Estou simplesmente adicionando uma exclusão das linhas apropriadas antes de imprimir { 3,5d ; p } .

    
por 24.08.2013 / 13:32
4

Você pode tentar a opção -A com grep , que especifica quantas linhas após a linha correspondente deve ser impressa. Junte isso com sed e você obteria as linhas necessárias.

grep -A 4 pattern input.txt | sed -e '2,4d'

Usando sed , excluímos o da segunda linha até o quarto.

    
por 24.08.2013 / 15:40
2

Aqui está uma maneira em Perl que pode lidar com um número arbitrário de linhas correspondentes:

perl -ne '/pattern/ && do{$c=$.; print}; $.==$c+4 && print' file > new_file'

Em Perl. a variável especial $. é o número da linha atual. Assim, toda vez que eu encontrar uma linha correspondente a pattern , imprimo e salvo seu número de linha como $c . Em seguida, imprimo novamente quando o número da linha atual é 4 maior do que o impresso anteriormente.

    
por 24.08.2013 / 16:14
0
awk 'c&&!--c;/img class=\"devil_icon/{c=4};/img class=\"devil_icon/' input.txt

Você está basicamente fazendo uma descoberta e substituindo. Você pode adicionar apenas um find no mesmo comando e ele imprimirá os dois:)

awk 'c&&!--c;/pattern/{c=4};/pattern/' input.txt
    
por 15.04.2014 / 22:47