146 votes

Comment sélectionner les lignes entre deux motifs de marqueurs qui peuvent apparaître plusieurs fois avec awk/sed

Utilisation de awk o sed comment puis-je sélectionner les lignes qui se trouvent entre deux motifs de marquage différents ? Il peut y avoir plusieurs sections marquées avec ces motifs.

Par exemple : Supposons que le fichier contient :

abc
def1
ghi1
jkl1
mno
abc
def2
ghi2
jkl2
mno
pqr
stu

Et le modèle de départ est abc et le motif final est mno Donc, j'ai besoin de la sortie comme :

def1
ghi1
jkl1
def2
ghi2
jkl2

J'utilise sed pour faire correspondre le modèle une fois :

sed -e '1,/abc/d' -e '/mno/,$d' <FILE>

Y a-t-il un moyen de sed o awk pour le faire de manière répétée jusqu'à la fin du fichier ?

226voto

fedorqui Points 42938

Utilisez awk avec un drapeau pour déclencher l'impression si nécessaire :

$ awk '/abc/{flag=1;next}/mno/{flag=0}flag' file
def1
ghi1
jkl1
def2
ghi2
jkl2

Comment cela fonctionne-t-il ?

  • /abc/ correspond aux lignes contenant ce texte, ainsi qu'à /mno/ fait.
  • /abc/{flag=1;next} définit le flag lorsque le texte abc est trouvé. Ensuite, il saute la ligne.
  • /mno/{flag=0} désactive le flag lorsque le texte mno est trouvé.
  • La finale flag est un modèle avec l'action par défaut, qui est de print $0 : si flag est égal à 1, la ligne est imprimée.

Pour une description plus détaillée et des exemples, ainsi que des cas où les motifs sont affichés ou non, voir Comment sélectionner les lignes entre deux motifs ? .

53voto

Jonathan Leffler Points 299946

Utilisation de sed :

sed -n -e '/^abc$/,/^mno$/{ /^abc$/d; /^mno$/d; p; }'

El -n signifie ne pas imprimer par défaut.

Le modèle recherche les lignes contenant seulement abc à juste mno et exécute ensuite les actions dans le { ... } . La première action supprime le abc la seconde la mno et la p imprime les lignes restantes. Vous pouvez assouplir les regex comme vous le souhaitez. Toutes les lignes situées en dehors de l'intervalle de abc .. mno ne sont tout simplement pas imprimés.

20voto

potong Points 18653

Cela pourrait fonctionner pour vous (GNU sed) :

sed '/^abc$/,/^mno$/{//!b};d' file

Effacer toutes les lignes sauf celles entre les lignes commençant par abc y mno

14voto

Ciro Santilli Points 3341
sed '/^abc$/,/^mno$/!d;//d' file

golfe deux caractères mieux que de ppotong {//!b};d

Les barres obliques vides // signifie : "réutiliser la dernière expression régulière utilisée". et la commande fait la même chose que la plus compréhensible :

sed '/^abc$/,/^mno$/!d;/^abc$/d;/^mno$/d' file

Ce site semble être POSIX :

Si un RE est vide (c'est-à-dire qu'aucun motif n'est spécifié), sed doit se comporter comme si le dernier RE utilisé dans la dernière commande appliquée (soit comme adresse, soit comme partie d'une commande de substitution) était spécifié.

10voto

FanDeLaU Points 79

Parmi les liens de la réponse précédente, celui qui l'a fait pour moi, en cours d'exécution. ksh sur Solaris, c'était ça :

sed '1,/firstmatch/d;/secondmatch/,$d'
  • 1,/firstmatch/d : de la ligne 1 jusqu'à la première fois que vous trouvez firstmatch , supprimer.
  • /secondmatch/,$d : dès la première apparition de secondmatch jusqu'à la fin du fichier, supprimer.
  • Le point-virgule sépare les deux commandes, qui sont exécutées en séquence.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X