web-dev-qa-db-fra.com

Imprimer les lignes d'un fichier entre deux motifs correspondants

Comment imprimer toutes les lignes entre deux lignes commençant par un motif pour la première ligne et se terminant par un autre motif pour la dernière ligne?


Mise à jour
Je suppose que c'était une erreur de mentionner que ce document est HTML. Il me semble avoir touché un nerf, alors oubliez ça. Je n'essaie pas d'analyser le HTML ou de faire quoi que ce soit d'autre que d'imprimer une section d'un document texte.


Considérez cet exemple:

aaa
bbb
pattern1
aaa pattern2
bbb
ccc
pattern2
ddd
eee
pattern1
fff
ggg

Maintenant, je veux tout imprimer entre la première instance de pattern1 commençant au début d'une ligne et pattern2 commençant au début d'une autre ligne. Je veux inclure le pattern1 et pattern2 lignes dans ma sortie, mais je ne veux rien après le pattern2 ligne.

pattern2 se trouve dans l'une des lignes de la section. Je ne veux pas m'arrêter là, mais cela est facilement résolu en indiquant le début de la ligne avec ^.

pattern1 apparaît sur une autre ligne après pattern2, mais je ne veux pas du tout regarder ça. Je cherche juste tout entre l'instance d'abord de pattern1 et la première instance de pattern2, inclus.

J'ai trouvé quelque chose qui m'y arrive presque en utilisant sed:

sed -n '/^pattern1/,/^pattern2/p' inputfile.txt

... mais cela recommence à imprimer à la prochaine instance de pattern1

Je peux penser à une méthode utilisant grep -n ... | cut -f1 -d: deux fois pour obtenir les deux numéros de ligne puis tail et head pour obtenir la section que je veux, mais j'espère une méthode plus propre. Peut-être que awk est un meilleur outil pour cette tâche?

Lorsque j'obtiendrai ce travail, j'espère le lier à un crochet git. Je ne sais pas encore comment faire ça non plus, mais je continue de lire et de chercher :)

Je vous remercie.

19
Vince

Vous pouvez faire quitter sed à un modèle avec sed '/pattern/q', vous avez donc juste besoin de vos correspondances, puis quittez la deuxième correspondance de motif:

sed -n '/^pattern1/,/^pattern2/p;/^pattern2/q'

De cette façon, seul le premier bloc sera affiché.

24
Fiximan

En règle générale, avec sed, il est facile d'imprimer des lignes d'une correspondance à une autre inclusivement:

$ seq 1 100 > test
$ sed -n '/^12$/,/^15$/p' test
12
13
14
15

Avec awk, vous pouvez faire la même chose comme ceci:

$ awk '/^12$/{flag=1}/^15$/{print;flag=0}flag' test
12
13
14
15

Vous pouvez les rendre non inclusifs comme ceci:

$ awk '/^12$/{flag=1;next}/^15$/{flag=0}flag' test
13
14

$ sed -n '/^12$/,/^15$/p' test | sed '1d;$d'
13
14
9
Will