web-dev-qa-db-fra.com

Comment grep les lignes entre le motif de début et de fin?

J'ai un fichier dont le contenu est le suivant:

zdk
aaa
b12
cdn
dke
kdn

Input1: aaa et cdn

Sortie 1:

aaa
b12
cdn

Entrée 2: zdk et dke

Sortie 2:

zdk
aaa
b12
cdn
dke

Je pourrais utiliser les commandes ci-dessous pour réaliser:

grep -a aaa -A2 file # Output 1
grep -a aaa -A4 file # Output 2

Mais dans le fichier, je ne sais pas quelle est l'occurrence (position) exacte du modèle de chaîne de fin (le fichier contient 20000 lignes)

Comment puis-je atteindre cet objectif?

31
Spike

grep ne vous aidera pas ici. C'est un travail mieux accompli avec sed en utilisant des expressions de plage:

$ sed -n '/aaa/,/cdn/p' file
aaa
b12
cdn
$ sed -n '/zdk/,/dke/p' file
zdk
aaa
b12
cdn
dke

sed -n supprime l'impression automatique, afin que les lignes soient imprimées juste si cela est explicitement demandé. Et cela se produit lorsque la plage /aaa/,/cdn/ arrive.

Ces expressions de plage sont également disponibles dans awk, où vous pouvez dire:

awk '/zdk/,/dke/' file

Bien sûr, toutes ces conditions peuvent être étendues à une expression rationnelle plus stricte comme sed -n '/^aaa$/,/^cdn$/p' file pour vérifier que les lignes se composent exactement de aaa et cdn, rien d'autre.

35
fedorqui

Cela peut être fait par sed

sed -n '
    /^aaa$/,/^cdn$/w output1
    /^zdk$/,/^dke$/w output2
    ' file
4
Costas

Voici la commande grep:

grep -o "aaa.*cdn" <(paste -sd_ file) | tr '_' '\n'

Vous pouvez obtenir une correspondance multiligne dans grep, mais vous devez utiliser Perl-regexp pour grep (-P - qui n'est pas pris en charge sur toutes les plates-formes, comme OS X), donc comme solution de contournement, nous remplaçons les nouvelles lignes par _ caractère et après grep, nous les modifions en arrière.

Vous pouvez également utiliser pcregrep qui prend en charge les modèles à plusieurs lignes (-M).

Ou utilisez ex:

ex +"/aaa/,/cdn/p" -scq! file
1
kenorb