Como grep -v e também excluir a próxima linha após a partida?

12

Como filtrar 2 linhas para cada linha correspondente ao greex regex?
este é o meu teste mínimo:

SomeTestAAAA
EndTest
SomeTestABCD
EndTest
SomeTestDEFG
EndTest
SomeTestAABC
EndTest
SomeTestACDF
EndTest

E obviamente eu tentei por exemplo grep -vA 1 SomeTestAA que não funciona.

a saída desejada é:

SomeTestABCD
EndTest
SomeTestDEFG
EndTest
SomeTestACDF
EndTest
    
por Behrooz 30.08.2015 / 00:49

4 respostas

13

Você pode usar grep com -P (PCRE):

grep -P -A 1 'SomeTest(?!AA)' file.txt

(?!AA) é o padrão lookahead negativo com largura zero garantindo que não haja AA após SomeTest .

Teste:

$ grep -P -A 1 'SomeTest(?!AA)' file.txt 
SomeTestABCD
EndTest
SomeTestDEFG
EndTest
SomeTestACDF
EndTest
    
por 30.08.2015 / 01:03
4

Veja aqui uma solução sed (com -n ou seja, sem impressão automática) que funciona com entradas arbitrárias:

sed -n '/SomeTestAA/!p          # if line doesn't match, print it
: m                             # label m
//{                             # if line matches
$!{                             # and if it's not the last line
n                               # empty pattern space and read in the next line
b m                             # branch to label m (so n is repeated until a
}                               # line that's read in no longer matches) but
}                               # nothing is printed
' infile

com uma entrada como

SomeTestAAXX
SomeTestAAYY
+ one line
SomeTestONE
Message body
EndTest
########
SomeTestTWO
something here
EndTest
SomeTestAABC
+ another line
SomeTestTHREE
EndTest
SomeTestAA
+ yet another line

executando

sed -n -e '/SomeTestAA/!p;: m' -e '//{' -e '$!{' -e 'n;b m' -e '}' -e'}' infile

saídas

SomeTestONE
Message body
EndTest
########
SomeTestTWO
something here
EndTest
SomeTestTHREE
EndTest

ou seja, remove exatamente as linhas que grep -A1 SomeTestAA infile selecionaria:

SomeTestAAXX
SomeTestAAYY
+ one line
--
SomeTestAABC
+ another line
--
SomeTestAA
+ yet another line
    
por 30.08.2015 / 03:23
3

Você pode ter mais sorte com algo que analisa regiões de várias linhas como registros únicos. Existe um sgrep que eu não usei muito.

Há também o awk, onde você pode definir o separador de registro de entrada e o separador de registro de saída para o que quiser.

pat="^SomeTestAA"
awk  'BEGIN{ RS=ORS="\nEndTest\n"} !/'"$pat/" foo

A maior parte do programa awk tem aspas simples, mas eu mudo para as aspas duplas no final, então a variável $pat shell pode ser expandida.

    
por 30.08.2015 / 01:03
3

Uma opção é usar p erl c ompatível r egular e xpressão grep :

pcregrep -Mv 'SomeTestAA.*\n' file

A opção -M permite que o padrão corresponda a mais de uma linha.

    
por 30.08.2015 / 01:12