Comment sélectionner des lignes entre deux motifs de marqueur qui peuvent se produire plusieurs fois avec awk/sed

utilisant awk ou sed Comment puis-je sélectionner des lignes qui se produisent entre deux motifs de marqueur différents? Il peut y avoir plusieurs sections marquées de ces motifs.

par exemple: Supposons que le fichier contient:

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

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

def1
ghi1
jkl1
def2
ghi2
jkl2

j'utilise sed pour correspondre au modèle une fois:

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

est-il possible dans sed ou awk de le faire à plusieurs reprises jusqu'à la fin du fichier?

90
demandé sur oberlies 0000-00-00 00:00:00

8 réponses

utiliser awk avec un indicateur 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?

  • /abc/ correspond aux lignes ayant ce texte, ainsi que /mno/ correspond.
  • /abc/{flag=1;next} définit le flag lorsque le texte abc est trouvé. Puis, il saute la ligne.
  • /mno/{flag=0} annule le flag lorsque le texte mno est trouver.
  • La finale flag est un modèle à l'action par défaut, qui est de print "1519110920" : 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 présentés ou non, voir Comment sélectionner des lignes entre deux motifs? .

140
répondu fedorqui 2017-05-23 12:02:56

par sed :

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

l'option -n signifie Ne pas imprimer par défaut.

le modèle cherche des lignes contenant juste abc à juste mno , puis exécute les actions dans le { ... } . La première action supprime la ligne abc ; la seconde la ligne mno ; et la p imprime les lignes restantes. Vous pouvez détendre les regexes si nécessaire. Toutes les lignes à l'extérieur du gamme de abc .. mno ne sont tout simplement pas imprimés.

35
répondu Jonathan Leffler 2013-08-01 08:47:40

cela pourrait marcher pour vous (GNU sed):

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

supprimer toutes les lignes sauf celles entre les lignes commençant par abc et mno

15
répondu potong 2013-08-01 09:39:57
sed '/^abc$/,/^mno$/!d;//d' file

golfs deux caractères de mieux que ppotong's {//!b};d

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

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

Ce semble être POSIX :

Si un RE est vide (aucun modèle n'est spécifié) sed doit se comporter comme si le dernier RE utilisé dans la dernière commande appliquée (soit comme adresse ou comme partie d'une commande de remplacement) a été spécifié.

12

D'après les liens de la réponse précédente, celui qui l'a fait pour moi, en lançant ksh sur Solaris, était ceci:

sed '1,/firstmatch/d;/secondmatch/,$d'
4
répondu FanDeLaU 2017-07-12 16:38:10

Don_crissti la réponse de Afficher uniquement le texte entre 2 correspondent au motif ?

firstmatch="abc"
secondmatch="cdf"
sed "/$firstmatch/,/$secondmatch/!d;//d" infile

qui est beaucoup plus efficace que L'application D'AWK, voir ici .

2
répondu Léo Léopold Hertz 준영 2017-04-13 12:36:28
perl -lne 'print if((/abc/../mno/) && !(/abc/||/mno/))' your_file
1
répondu Vijay 2013-08-01 09:13:08

quelque chose comme ceci fonctionne pour moi:

"151920920 de fichier".awk:

BEGIN {
    record=0
}

/^abc$/ {
    record=1
}

/^mno$/ {
    record=0;
    print "s="s;
    s=""
}

!/^abc|mno$/ {
    if (record==1) {
        s = s"\n""151900920"
    }   
}

par awk -f file.awk data ...

edit: O_o fedorqui solution est beaucoup mieux/plus jolie que la mienne.

1
répondu pataluc 2014-06-11 11:32:58