Corresponder patternA e imprimi-lo somente quando patternB for correspondido, incluindo a seguinte linha

4

Eu estou olhando para obter todas as linhas que têm a palavra 'search_string' + a linha após ele + a linha correspondente 'mod' antes dele.
Eu tentei:

grep -n 'mod\|search_string' ip | grep --before 1 search_string> inter  
grep -n --after 1 search_string ip >> inter  
sort -t':' -k1,1n -u inter -o op

Existe uma maneira melhor?

Arquivo:

mod start1  
some lines  
mod start2  
other lines  
mod start3  
 many other lines  
 search_string yada yada  
 hello  
 many other lines  
 search_string yada yada  
 bye  
mod start4  
 search_string baba baba  
 this too  
mod start5  

Resultado esperado:

mod start3  
 search_string yada yada   
 hello  
 search_string yada yada  
 bye  
mod start4  
 search_string baba baba  
 this too
    
por romi 25.08.2018 / 20:46

3 respostas

4
awk '
   $0 ~ /mod/ { md=$0 }
   $0 ~ /search_string/ { if(md!="") { print md }; md="" ; print; getline; print }
   '

Explicação:

  • Uma linha contendo mod é salva como md .
  • Uma linha contendo search_string dispara a impressão da md salva anteriormente, a própria linha e a próxima linha.
  • if(md!="") e md="" estão lá para garantir que você não receba mod linhas duplicadas quando houver muitos search_string -s sob um único mod ( mod start3 em seu exemplo).

Nota:

  • Uma linha contendo mod e search_string quebrará essa lógica.
por 25.08.2018 / 21:27
2

Seu arquivo contém caracteres "retorno de carro". É melhor removê-los no Unix. Para imprimir o que a seqüência de comandos que você publicou imprimir (com retornos de carro removidos), tente:

awk '{gsub(/\r/,"")}
     /mod/          { a = $0 }
     /search_string/{ if(a!=""){print(a);a=""}
                      print;getline;print
                    }
    ' infile

Ou como um verso:

$ awk '{gsub(/\r/,"")}/mod/{a=$0}/search_string/{if(a!=""){print(a);a=""}print;getline;print}' infile

mod start3  
 search_string yada yada  
 hello  
 search_string yada yada  
 bye  
mod start4  
 search_string baba baba  
 this too  

Como é possível usar um separador de registro de vários caracteres no (GNU) awk, podemos definir o separador de registro como mod e imprimir apenas os registros que contêm search_string . O printf é necessário para reconstruir o registro original.

Para imprimir o que você postou como "Saída esperada", tente:

awk '/search_string/{printf("mod%s", $0)}' RS=mod infile
    
por 25.08.2018 / 21:25
0

Se você quiser isso em um script Python:

# Read file into memory.
with open('myfile.txt') as f:
    lines = [line.rstrip() for line in f]

# Loops through lines backwards, looking for string and optionally mod.
output_lines = list()
find_mod = False
for i, line in enumerate(lines[::-1]):
    if 'search_string' in line:
        output_lines.append(lines[::-1][i-1])
        output_lines.append(lines[::-1][i])
        find_mod = True
    elif find_mod and 'mod' in line:
        output_lines.append(lines[::-1][i])
        find_mod=False

print("\n".join(output_lines[::-1]))
    
por 26.08.2018 / 04:36