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 leflaglorsque le texteabcest trouvé. Puis, il saute la ligne. -
/mno/{flag=0}annule leflaglorsque le textemnoest trouver. - La finale
flagest un modèle à l'action par défaut, qui est deprint "1519110920": siflagest é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.