web-dev-qa-db-fra.com

Afficher tout le fichier jusqu'au match

grep --before-context 5 affiche 5 lignes avant le match.

Je veux tout montrer avant le match.
Faire grep --before-context 99999999 fonctionnerait mais ce n'est pas très ... professionnel.

Comment afficher tout le fichier jusqu'au match?

78
Nicolas Raoul

Sed est mieux pour ça.

Faites juste:

sed '/PATTERN/q' FILE

Cela fonctionne comme ceci:

Pour chaque ligne, nous regardons si elle correspond à /PATTERN:

  • si oui, nous l'imprimons et quittons
  • sinon, nous l'imprimons

C'est la solution la plus efficace, car dès qu'elle voit PATTERN, elle se ferme. Sans q, sed continuerait à lire le reste du fichier et ne ferait rien avec. Pour les gros fichiers, cela peut faire la différence.

Cette astuce peut également être utilisée pour émuler head:

sed 10q FILE
104
Mikel

sed peut remplacer la plupart des fonctionnalités de grep.

sed -n '1,/<pattern>/ p' <file>

Cela signifie imprimer à partir de la première ligne jusqu'à ce que le motif corresponde.

Quelques exemples de gamme

sed -n '/<pattern>/,$ p' <file> # from pattern to end of file
sed -n '/<pattern1>/,/<pattern2>/ p' <file> # from pattern1 to pattern2
39
forcefsck

imprimer jusqu'au match inclus:

awk '{print} /pattern/ {exit}' filename
sed '/pattern/q' filename

imprimer jusqu'à MAIS NON compris le match:

awk '/pattern/ {exit} {print}' filename
sed '/pattern/Q' filename
39
glenn jackman

Pour les personnes qui choisissent de ne se souvenir que des outils de base dans le travail quotidien et qui souhaitent accepter des solutions moins élégantes et moins efficaces:

head -n $(grep -n pattern filename | cut -d: -f1) filename

Si cette commande est destinée à un script, je chercherai des solutions plus élégantes (et éventuellement efficaces). S'il s'agit d'une commande unique ou d'un script à jeter, je m'en fiche.

1
lesmana

Ajout à la réponse de Mikel ci-dessus ...


Pour imprimer toutes les lignes jusqu'à la première ligne de FILE contenant PATTERN, sans inclure , essayez:

  • sed '/.*PATTERN.*/{s///;q;}' FILE

Cela correspond à la ligne entière contenant le modèle, le remplace par une ligne vierge, puis se ferme sans traiter le reste du fichier.


Post-script:

La manière la plus simple/la plus claire à laquelle j'ai pu penser pour empêcher l'impression d'une nouvelle ligne supplémentaire à la fin (sans impliquer un autre outil), était de relancer sed et de supprimer la nouvelle ligne finale:

sed '/.*PATTERN.*/{s///;q;}' FILE | sed '$d'

... et puisque nous supprimons maintenant cette ligne de toute façon, notre travail précédent est redondant et nous pouvons simplifier pour:

sed '/PATTERN/q' FILE | sed '$d'
1
Jim Grisham

Les méthodes GNU grep pures suivantes ne sont pas efficaces.

Recherchez tout jusqu'à la première instance de la chaîne " foo " dans barre de fichier , en utilisant trois greps:

grep -m 1 -B $(grep -n -m 1 foo bar | grep -o '^[0-9]*') foo bar

Correspondance avec la dernière instance de " foo ":

grep -oPz "(?s)[^\n]*${s}.*?\n.*?foo.*?\n" bar

Remarque: les détails sur le dernier grep peuvent être trouvés dans: Regex (grep) pour la recherche multi-lignes nécessaire .

1
agc

Vous pouvez également utiliser l'un des éléments suivants

tac ./test | grep -B $(cat ./test | wc -l) -m 1 'pattern'|tac 

ou

tac ./test |head -n $(tac ./test | grep -n 'pattern' | cut -d: -f1 | head -n 1)|tac

ou

tac ./test |sed ':a;N;$!ba;s/\n/'"pattern"'/g' | sed 's/'"patternpattern"'/\n/g'|head -n 1|sed 's/'"pattern"'/\n/g'|tac

La première option est très similaire à ce que l'OP a suggéré seulement, elle s'assure de montrer suffisamment de lignes avant le contexte en comptant les lignes dans le fichier

La deuxième option recherche le numéro de ligne de la première correspondance (vous pouvez également changer cela en changeant la "tête" intérieure) et utilise la tête sur ce numéro

La dernière option remplace toutes les nouvelles lignes par la correspondance et remplace ensuite deux correspondances adjacentes par une nouvelle ligne. La sortie de ceci est une ligne pour chaque bloc de texte entre deux correspondances. Après cela, il utilise 'head' pour choisir la première ligne (mwaning le bloc de texte jusqu'à la première correspondance) et ensuite retraduit chaque correspondance en une nouvelle ligne. cette option ne fonctionne que si le fichier est au format suivant

pattern
texttexttext
texttexttext texttexttext
texttexttexttexttexttexttexttexttext
pattern
texttexttext
pattern 
texttexttext
texttexttexttexttexttexttexttexttext

et ainsi de suite

0
user122778