texto entre 2 palavras com algumas linhas antes de padrões

1

Como posso encontrar linhas entre duas palavras com três linhas antes de START_WORD em sed ou grep ou ...

por exemplo, a saída de um comando é:

my name is
Mansour
and I confuse to
use sed
or grep for
piping my command output
to get 
my ideal output

e eu quero o meu fora depois de canalizar o comando com sed ou grep no START_WORD = comando e END_WORD = ideal:

and I confuse to
use sed
or grep for
piping my command output
to get 
my ideal output
    
por Mansour 09.02.2016 / 07:10

2 respostas

2

Você pode fazer:

grep -Pzo '(?s)\n\K([^\n]*\n){3}[^\n]*command[^\n]*\n.*?\n[^\n]*ideal[^\n]*(?=\n)' file.txt
  • -P ativa o Regex compatível com Perl, -z torna os dados de entrada separados em ASCII NUL em vez da nova linha usual, -o deixa apenas a parte correspondida

  • (?s) é o modificador DOTALL, isso nos permite corresponder a nova linha ( \n ) com . token

  • \n\K([^\n]*\n){3} corresponde \n primeiro e, em seguida, descarta a correspondência \K , ([^\n]*\n){3} corresponde a três linhas antes da linha que contém command

  • [^\n]*command[^\n]*\n.*?\n[^\n]*ideal[^\n]*(?=\n) corresponde a todas as linhas a partir da linha que tem command até a linha que contém ideal

Exemplo:

% cat file.txt
my name is
Mansour
and I confuse to
use sed
or grep for
piping my command output
to get 
my ideal output

% grep -Pzo '(?s)\n\K([^\n]*\n){3}[^\n]*command[^\n]*\n.*?\n[^\n]*ideal[^\n]*(?=\n)' file.txt
and I confuse to
use sed
or grep for
piping my command output
to get 
my ideal output
    
por heemayl 09.02.2016 / 14:37
1

Outra maneira de usar o Perl:

perl -ne 'BEGIN{ my @buffer } unshift(@buffer, $_); splice(@buffer, 4); if(/\bcommand\b/) { print(reverse(@buffer)); while(<>) { print(); /\bideal\b/ && exit } exit }' file
  • n : faz com que o Perl assuma o seguinte loop em torno do seu programa, o que faz com que seja iterado sobre argumentos de nome de arquivo como sed -n ou awk:

    LINE:
      while (<>) {
          ...             # your program goes here
      }
    
  • -e : pode ser usado para inserir uma linha de programa.
  • BEGIN{ my @buffer } unshift(@buffer, $_); splice(@buffer, 4); if(/\bcommand\b/) { print(reverse(@buffer)); while(<>) { print(); /\bideal\b/ && exit } exit } : insere a linha atual no início de um buffer e trunca o buffer para um tamanho de 4; se a linha atual contiver a palavra command , imprime o buffer na ordem inversa e percorre todas as linhas restantes imprimindo-as; se uma linha impressa continha ideal ou o final do arquivo foi atingido, sai.
% cat file
my name is
Mansour
and I confuse to
use sed
or grep for
piping my command output
to get 
my ideal output
% perl -ne 'BEGIN{ my @buffer } unshift(@buffer, $_); splice(@buffer, 4); if(/\bcommand\b/) { print(reverse(@buffer)); while(<>) { print(); /\bideal\b/ && exit } exit }' file
and I confuse to
use sed
or grep for
piping my command output
to get 
my ideal output
%
    
por kos 09.02.2016 / 15:17