Grep começando de um texto fixo, até a primeira linha em branco

8

Eu tenho um arquivo prova.txt como este:

Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random2
random3
random4

extra1
extra2
bla

Start to grab from here: 2
fix1
fix2
fix3
fix4
random1546
random2561

extra2
bla
bla

Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random22131

e eu preciso sair de "Start to grab here" para a primeira linha em branco. A saída deve ser assim:

Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random2
random3
random4

Start to grab from here: 2
fix1
fix2
fix3
fix4
random1546
random2561

Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random22131

Como você pode ver as linhas depois de "Start to grab here" são aleatórias, então -A -B grep flag não funciona:

cat prova.txt | grep "Start to grab from here" -A 15 | grep -B 15 "^$" > output.txt

Você pode me ajudar a encontrar uma maneira de pegar a primeira linha que será pega (como "Comece a pegar daqui"), até uma linha em branco. Eu não posso prever quantas linhas aleatórias eu terei depois de "Start to grab from here".

Qualquer solução compatível com unix é apreciada (grep, sed, awk é melhor que perl ou similar).

EDITADO: depois da brilhante resposta de @ john1024, gostaria de saber se é possível:

1 ° classifica o bloco (de acordo com o Start para pegar daqui: 1 depois 1 depois 2)

2 ° remove 4 (alfabeticamente aleatórios) linhas fix1, fix2, fix3, fix4, mas são sempre 4

3 ° eventualmente remove dupes aleatórios, como sort -u command

A saída final deve ser assim:

# fix lines removed - match 1 first time
Start to grab from here: 1
random1
random2
random3
random4

#fix lines removed - match 1 second time
Start to grab from here: 1
#random1 removed cause is a dupe
random22131

#fix lines removed - match 2 that comes after 1
Start to grab from here: 2
random1546
random2561

ou

# fix lines removed - match 1 first time and the second too
Start to grab from here: 1
random1
random2
random3
random4
#random1 removed cause is a dupe
random22131

#fix lines removed - match 2 that comes after 1
Start to grab from here: 2
random1546
random2561

A segunda saída é melhor que a primeira. Alguma outra magia de comando unix é necessária.

    
por heisen 24.10.2016 / 20:40

2 respostas

10

Usando o awk

Tente:

$ awk '/Start to grab/,/^$/' prova.txt
Start to grab from here: 1
random1
random2
random3
random4

Start to grab from here: 2
random1546
random2561

Start to grab from here: 3
random45
random22131

/Start to grab/,/^$/ define um intervalo. Ele começa com qualquer linha que corresponda a Start to grab e termina com a primeira linha vazia, ^$ , a seguir.

Usando sed

Com uma lógica muito semelhante:

$ sed -n '/Start to grab/,/^$/p' prova.txt
Start to grab from here: 1
random1
random2
random3
random4

Start to grab from here: 2
random1546
random2561

Start to grab from here: 3
random45
random22131

-n diz ao sed para não imprimir nada a menos que explicitamente o solicitemos. /Start to grab/,/^$/p diz para imprimir todas as linhas no intervalo definido por /Start to grab/,/^$/ .

    
por 24.10.2016 / 20:43
0

Estou postando uma solução alternativa, pois pode ser útil para alguns casos de uso de pessoas. Esta solução não atende exatamente aos requisitos declarados, para a melhor solução, veja a resposta de @ John1024.

Você pode usar o awk com o Record Separator configurado para uma string vazia, o awk irá interpretá-las como novas linhas em branco:

$ awk '/Start/' RS= prova.txt 
Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random2
random3
random4
Start to grab from here: 2
fix1
fix2
fix3
fix4
random1546
random2561
Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random22131

Esta versão não preserva as novas linhas em branco na saída. Ele também mostrará o contexto antes da partida, se presente. Este comportamento pode ser muito útil quando se está procurando por algo em um arquivo e você deseja ver o bloco delimitado por nova linha do qual ele faz parte, por exemplo:

$ awk '/random1546/' RS= prova.txt 
Start to grab from here: 2
fix1
fix2
fix3
fix4
random1546
random2561

Por exemplo, acho isso útil ao usar o grepping para coisas em ini files.

    
por 13.11.2018 / 00:37