J'essaie de supprimer une plage en utilisant sed
. La plage est à partir d'une correspondance connue et des 2 lignes suivantes. Disons que je veux supprimer toutes les lignes commençant par Don't
puis les 2 lignes qui suivent.
Veuillez noter que je fais également des substitutions dans un fichier de commande sed. En tant que tel, j'évite d'utiliser -n
et / p
dans mon espace solution.
Pour une raison quelconque, je souhaite me limiter à un seul appel de sed.
Voici mes données (data.txt):
/^Don't/,/^Don't/+2d /^Don't/,{/^Don't/+2}d
Voici ma sortie attendue:
sed: 1: delete_dont_plus_2.sed: expected context address
Voici une tentative pour ceci:
/^Don't/,+2d
Avec ceci comme delete_dont_plus_2.sed
:
sed -f delete_dont_plus_2.sed data.txt
Voici mon résultat:
Print Me Please Output This line We should see this line And this one, too.
J'ai aussi essayé ces :
Print Me Please Output This line Don't Print Me and 2 more lines This line is no good So is this one We should see this line And this one, too.
Deuxième approche à cette question:
Disons que nous voulions rendre ce code un peu plus robuste. Aujourd'hui, il y a encore 2 lignes à supprimer, mais qui sait combien de lignes il y aura dans le futur. Disons que nous voulons supprimer jusqu'à, mais sans inclure Nous devrions voir cette ligne
. Dans cette variante de la question, les résultats sont exactement les mêmes. Encore une fois, considérons un BSD sed limité afin que nous ne puissions pas utiliser une expression comme / ^ Don't /, / ^ Nous devrions voir cette ligne / -1d
.
Merci!
3 Réponses :
Vous utilisez probablement un sed qui ne prend pas en charge les adresses sous la forme regexp, + n
. Voici une solution de contournement pour ce cas particulier:
awk 'index($0,"Don\047t")==1{d=1} $0=="We should see this line"{d=0} !d' file
Il lit simplement deux lignes supplémentaires dans l'espace du motif lorsque ^ Don't
est trouvé et les supprime complètement.
Mais de toute façon, je pense que sed n'est pas le bon outil pour cela, vous devriez utiliser awk à la place. Par exemple:
/^Don't/,/^We should see this line/{/^We should see this line/!d;}
cf: Impression avec sed ou awk d'une ligne suivant un motif correspondant
wrt
Disons que nous voulons supprimer jusqu'à, mais sans inclure
Nous devrions voir cette ligne
. Dans cette variante de la question, les résultats sont exactement les mêmes.
En utilisant sed, vous devrez écrire deux fois la même RE:
awk '/^Don\047t/{c=2;next} !(c&&c--)' file
En utilisant awk, vous n'avez même pas besoin de RE:
/^Don't/{N;N;d;}
Travaille pour moi. J'ai dû y ajouter un peu de plaisir MAC: / ^ Don't / {N; N; d;}
(c'est-à-dire le dernier semi). J'apprécie également la réponse awk. Awk est presque toujours mon outil préféré (par rapport à sed). Cependant, j'ai déjà un gros fichier de commandes sed avec principalement des substitutions, donc je suis contraint. Merci de votre aide
@Mark de toute façon, je pense que vous devriez installer GNU sed au lieu de vous limiter à la rigueur de BSD sed
Je vous entends, mais je ne peux pas parler pour tous les autres utilisateurs de Mac de ma communauté. Dans un sens, je suis coincé avec le plus petit dénominateur commun. Merci encore pour votre aide. Comme question supplémentaire, comment le script changerait-il si nous ne savions pas combien de lignes supprimer? Nous voulions plutôt supprimer jusqu'à, mais sans inclure la première ligne qui commençait comme ceci '/ ^ Nous devrions voir cette ligne /'. Avec cette variante de la question, la sortie devrait être la même.
pour awk, voir aussi: stackoverflow.com/questions/17908555/...
Cette solution peut ne pas fonctionner lorsque l'expression rationnelle est la dernière ou la seconde de la dernière ligne car l'instruction N
essaiera de lire au-delà de la fin du fichier et échouera, imprimant ce qui se trouve dans l'espace de motif. Peut-être que le fichier sed '/ ^ Don't / {$! N; $! N; d;}'
empêcherait cela.
@potong vous avez raison, faites une modification ou laissez votre commentaire ici pour que les futurs lecteurs puissent le voir. Merci
Avec GNU sed:
Print Me Please Output This line We should see this line And this one, too.
Sortie:
sed "/^Don't/,+2d" file
Cela pourrait fonctionner pour vous (GNU sed):
sed '/^Don'\''t/{s/.*/X/;h;d};x;/X/!{x;b};s/^/X/;/^XX\{2\}/s/.*//;x;d' file
Cette solution tient un compte à partir du moment où l'expression rationnelle est rencontrée.
N.B. Si l'une des deux lignes suivant l'expression rationnelle est aussi l'expression rationnelle, le décompte est redémarré.
Une solution moins spécifique à GNU et programmatique:
sed '/^Don'\''t/{s/.*/X/;h;d};x;/X/!{x;b};s/^/X/;/^XXX/z;x;d' file