Grep à partir d'un texte fixe, jusqu'à la première ligne vierge

9

J'ai un fichier prova.txtcomme celui-ci:

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

et je dois passer de "Commencer à saisir ici" à la première ligne vierge. La sortie devrait être comme ceci:

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

Comme vous pouvez le voir, les lignes après "Commencer à saisir ici" sont aléatoires, donc l'indicateur -A -B grep ne fonctionne pas:

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

Pouvez-vous m'aider à trouver un moyen de capturer la première ligne qui sera saisie (comme "Commencer à saisir à partir d'ici"), jusqu'à une ligne vierge. Je ne peux pas prédire combien de lignes aléatoires j'aurai après "Commencer à saisir à partir d'ici".

Toute solution compatible Unix est appréciée (grep, sed, awk est meilleur que perl ou similaire).

EDITED: après une brillante réponse de @ john1024, je voudrais savoir s'il est possible de:

1 ° trier le bloc (selon Commencer à saisir d'ici: 1 puis 1 puis 2)

2 ° supprimer 4 lignes (alphabétiquement aléatoires) fix1, fix2, fix3, fix4 mais sont toujours 4

3 ° supprimer éventuellement les dupes aléatoires, comme la commande sort -u

La sortie finale doit être comme ceci:

# 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

La deuxième sortie est meilleure que la première. Une autre magie de commande unix est nécessaire.

heisen
la source
1
Ceci est vraiment utile pour récupérer la trace de pile pour un thread particulier à partir de la sortie jstack java. Heureux d'avoir trouvé ce Q & A!
BenjaminBallard du

Réponses:

13

Utiliser awk

Essayer:

$ 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/,/^$/définit une plage. Il commence par n'importe quelle ligne qui correspond Start to grabet se termine par la première ligne vide ^$, qui suit.

Utilisation de sed

Avec une logique très similaire:

$ 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

-ndit à sed de ne rien imprimer à moins que nous ne le lui demandions explicitement. /Start to grab/,/^$/plui indique d'imprimer toutes les lignes dans la plage définie par /Start to grab/,/^$/.

John1024
la source
Votre solution est parfaite, j'ai édité ma demande pour ajouter quelque chose. Relly apprécie votre aide. Merci
heisen
1

Je poste une solution alternative car elle peut être utile à certains cas d'utilisation. Cette solution ne répond pas exactement aux exigences énoncées, pour la meilleure solution, voir la réponse de @ John1024.

Vous pouvez utiliser awk avec le séparateur d'enregistrements défini sur une chaîne vide, awk les interprétera comme des retours à la ligne vierges:

$ 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

Cette version ne conserve pas les sauts de ligne vides dans la sortie. Il montrera également le contexte avant le match s'il est présent. Ce comportement peut être très utile lorsque vous recherchez quelque chose dans un fichier et que vous souhaitez voir le bloc délimité par la nouvelle ligne dont il fait partie, par exemple:

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

Par exemple, je trouve cela utile lors de la recherche de choses dans des inifichiers.

htaccess
la source