Imprime várias linhas após a nth ocorrência no bash

4

Estou procurando uma maneira de pesquisar a enésima ocorrência de um padrão e imprimir k linhas após o padrão. Acho que awk funcionaria melhor que grep nesse caso, mas não consigo descobrir como fazer isso corretamente ...

Digamos que eu tenha o seguinte arquivo de texto:

Draft  
blablablabla  
tralalalalala  
Draft  
blablablabla  
tralalalalala  
Draft  
important line 1  
important line 2  
Draft   
blablablabla   
tralalalalala  

Neste caso, n=3 e k=2 , quero imprimir as duas linhas após a 3ª ocorrência do padrão "Rascunho". No meu caso específico, nek podem variar.

É uma maneira simples de fazer isso?

    
por Mils 01.12.2015 / 19:12

5 respostas

1

Você pode usar grep e tail para conseguir isso:

$ n=3
$ k=2
$ grep -m "$n" -A "$k" 'Draft' input.txt | tail -n "$k"
important line 1  
important line 2  
$ 

A opção -m "$n" para o grep especifica para parar após a n th corresponder, e -A "$k" diz ao grep para gerar k linhas depois de cada correspondência. Em seguida, canalizamos isso para tail -b "$k" para gerar apenas as linhas k .

    
por 01.12.2015 / 23:59
7

Perl para o resgate:

 perl -sne '$c++ if /Draft/;
            if ($c == $n) { print scalar <> for 1 .. $k; }
           ' -- -n=3 -k=2 < input
  • -s analisa as opções -n=3 e cria as variáveis.
  • -n lê a linha de entrada por linha.
  • <> o operador de diamante lê a entrada.
  • O escalar é necessário para ler apenas uma linha da entrada, caso contrário imprimir forçaria o contexto da lista no operador de diamantes e imprimiria todas as linhas restantes.
por 01.12.2015 / 19:20
5

awk: imprime as linhas entre as linhas 3 e 4 "rascunho".

awk -v n=3 '/Draft/ { p = (++num == n) ; next }; p' file

Há uma otimização a ser feita: sair quando o 4º rascunho for visto.

    
por 01.12.2015 / 20:32
1

Via awk

awk -v "k=2" -v "n=3" \
    '/^Draft/ {i++} 
    i==n-1 && x==0 {x++;next} 
    x>=1 && x<=k {print;x++} 
    x>k {exit}' foo
  • /^Draft/ {i++} incremento i para contar Draft
  • i==n-1 && x==0 {x++; next} pule a linha com a ocorrência n nd de Draft e defina x para imprimir a primeira linha após o n nd Draft
  • x>=1 && x<=k {print;x++} imprime as próximas k linhas
  • x>k {exit} e sair
por 01.12.2015 / 19:58
0
sed  -ne'/^\(.*\n\)*Draft *$/G'  \
     -e's/\n/&/3;t$' -e'N;D;:$'  \
     -e's///g;//!n;N;G;s/\n//2'  \
     -etq -e/.$/b$ -e:q -e'p;q' <in >out
important line 1
important line 2
    
por 02.12.2015 / 06:00