Imprimir linha correspondente e enésima linha da linha correspondente


18

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 apenas imprime a linha correspondente.

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

Preciso imprimir apenas a linha correspondente e a quarta linha.


Use egrep "pattern" -A4
Valentin Bajrami

@ val0x00ff que imprime as linhas entre também .. ou seja: ele imprime próximos 4 linhas a partir da linha combinado
Debal

você está dizendo "Estou tentando imprimir a linha correspondente e a quarta linha da linha correspondente". Isto grep -A 4 "pattern" file | sed -n '4p'faz exatamente o que você quer, a menos que eu estou mal-entendido que você
Valentin Bajrami

não, não faz. A saída do código acima foi </td>que não é a linha 4
Debal

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 correspondentes pattern. Quando encontra uma correspondência, armazena o número do registro ( NR) na matriz nr. Ele também armazena o quarto registro NRna mesma matriz. Isso é feito pelo nr[NR+4]. Cada registro ( NR) é verificado para ver se está presente na nrmatriz; nesse caso, o registro é impresso.

A segunda solução funciona essencialmente da mesma maneira, exceto quando encontra a patternlinha impressa e, em seguida, armazena o quarto registro à frente na matriz nre depois passa para o próximo registro. Então, quando awkencontrar esse 4º registro, o NR in nrbloco será executado e imprimirá esse registro +4 depois.

Exemplo

Aqui está 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 1ª 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

3
Bom, +1. Você está usando muitos awkatalhos aqui. Você pode adicionar uma breve explicação (coisas como impressão estão implícitas no awk e que matrizes são associativas etc.)?
terdon

concordo com @terdon, por favor, poderia explicar um pouco o código.
Debal 24/08/13

@slm Obrigado por melhorar e fornecer a resposta completa!
Valentin Bajrami

11
Obrigado pela resposta, eu também aprendi algo novo.
slm

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 da impressão { 3,5d ; p }.


sua expressão produz um erro: sed: -e expression #1, char 18: unknown option to s'`
minerals

4

Você pode tentar a -Aopção com grep, que especifica quantas linhas após a linha correspondente devem ser impressas. Junte isso sede você obterá as linhas necessárias.

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

Usando sed, excluímos da segunda linha até a quarta.


3
Isso pressupõe uma única correspondência patternno arquivo.
terdon

2

Aqui está uma maneira no 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, cada vez que encontro uma linha correspondente pattern, imprimo-a e salvo o número da linha como $c. Em seguida, imprimo novamente quando o número da linha atual é 4 a mais do que o impresso anteriormente.


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

Você está essencialmente fazendo uma busca e substituição. Você pode adicionar apenas uma descoberta ao mesmo comando e ele imprimirá os dois :)

awk 'c&&!--c;/pattern/{c=4};/pattern/' input.txt
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.