J'essaie de supprimer les lignes entre deux motifs, y compris les lignes avec les motifs eux-mêmes, si un autre motif est trouvé entre eux, mais je ne sais pas comment y remédier. et que vous souhaitez supprimer les lignes 6 à 11 car le motif autre que celui-ci
se trouve entre les motifs start
et end
:
/^start$/{$!{N;/^start\n(.*\n)*notthis.*\n(.*\n)*end/d;ty;P;D;:y}}
J'ai changé ce que je pensais comprendre de cette réponse en quelque chose comme ceci, mais cela ne fonctionne pas:
start AHBUe3Ar5NoD 3EcuCcD2QCja 7VmlKFbD8Rbi end start OgytsRhZbD8T notthis 0PlcUh2RLvVW tsz2S80SyW9p end start dQ5qiZCvBqcK SufdS40X1Sh2 B1cyNshOj2Z4 end
Est-ce parce que N
ajoute seulement la ligne suivant le modèle initial ^ start $ à l'espace de motif et ignore ce qui suit? Et quelle serait la bonne façon de réaliser ce que j'essaye de faire?
3 Réponses :
sed est pour des substitutions simples sur des chaînes individuelles, c'est tout . Pour toute autre chose, vous devriez utiliser awk, par exemple avec GNU awk pour mult-char RS ce bref script produira la sortie que vous voulez à partir de l'entrée que vous avez postée:
$ cat tst.awk /start/ { f = 1 } f { rec = rec $0 ORS if ( /end/ ) { if ( rec !~ /notthis/ ) { printf "%s", rec } rec = "" f = 0 } } $ $ awk -f tst.awk file start AHBUe3Ar5NoD 3EcuCcD2QCja 7VmlKFbD8Rbi end start dQ5qiZCvBqcK SufdS40X1Sh2 B1cyNshOj2Z4 end
ou plus claire, plus robuste et plus facile à améliorer avec n'importe quel awk: p>
$ awk 'BEGIN{RS=ORS="end\n"} !/notthis/' file start AHBUe3Ar5NoD 3EcuCcD2QCja 7VmlKFbD8Rbi end start dQ5qiZCvBqcK SufdS40X1Sh2 B1cyNshOj2Z4 end
Ce qui précède fonctionnera de manière efficace et robuste en utilisant n'importe quel awk dans n'importe quel shell sur chaque boîte UNIX, est facile à comprendre et facile à modifier si / quand vos exigences changent.
Merci, fonctionne comme un charme. Pourriez-vous expliquer les deux?
Le premier lit un enregistrement entier (bloc de texte multiligne) à la fois où chaque enregistrement se termine par end \ n
et imprime l'enregistrement s'il ne contient pas notthis code >. Le second définit un indicateur lorsque
start
est trouvé, construit l'enregistrement une ligne à la fois pendant que cet indicateur est défini, puis lorsque end
est trouvé, imprime l'enregistrement si il ne contient pas rien de tel
. Faites-moi savoir si vous avez des questions spécifiques sur la syntaxe après avoir jeté un coup d'œil à la page de manuel awk.
Voici un autre script awk
. J'espère correspondre à la description partielle du problème.
script.awk
start AHBUe3Ar5NoD 3EcuCcD2QCja 7VmlKFbD8Rbi end start OgytsRhZbD8T 0PlcUh2RLvVW tsz2S80SyW9p end notthis start dQ5qiZCvBqcK SufdS40X1Sh2 B1cyNshOj2Z4 end notthis
input.txt
XXX
en cours d'exécution:
awk -f script.awk input.txt
sortie:
start AHBUe3Ar5NoD 3EcuCcD2QCja 7VmlKFbD8Rbi end start OgytsRhZbD8T notthis 0PlcUh2RLvVW tsz2S80SyW9p end notthis start dQ5qiZCvBqcK SufdS40X1Sh2 B1cyNshOj2Z4 notthis end notthis
Assurez-vous de comprendre la discussion sur stackoverflow.com/q/23934486/1745001 si vous envisagez d'utiliser une expression de plage .
Cela pourrait fonctionner pour vous (GNU sed):
sed '/^start/{:a;N;/end$/!ba;/notthis/d}' file
Rassemblez les lignes entre start
et end
et si elles contiennent la chaîne notthis
les supprimer.
Espérons qu'il arrive un moment lors de l'écriture d'un script rempli de runes comme
/^start$/{$!{N;/^start\n(.*\n)*notthis.*\n(.*\n) * end / d; ty; P; D;: y}}
quand vous pensez à vous-même - "qu'est-ce que je fais ???"!