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?
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 leflag
lorsque le texteabc
est trouvé. Puis, il saute la ligne. -
/mno/{flag=0}
annule leflag
lorsque le textemno
est trouver. - La finale
flag
est un modèle à l'action par défaut, qui est deprint "1519110920"
: siflag
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? .
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.
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
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é.
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'
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 .
perl -lne 'print if((/abc/../mno/) && !(/abc/||/mno/))' your_file
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.