Comment supprimer toutes les lignes entre deux modèles dans un fichier à l'aide de sed .
Ici, le modèle est // test
et // endtest
, contenu du fichier:
blah blah blah c f f [ ] //test //endtest l dsf dsfs
Résultat attendu:
blah blah blah c f f [ ] //test all text to be deleted line1 line2 xyz amv { //endtest l dsf dsfs
3 Réponses :
Avec awk:
$ awk '/\/\/endtest/{p=0} !p; /\/\/test/{p = 1}' file blah blah blah c f f [ ] //test //endtest l dsf dsfs
Vous devez supprimer votre réponse car il est clairement écrit que la solution doit être résolue avec sed. Ou?
@YesThatIsMyName non, la question a été modifiée après avoir répondu
Ensuite, vous recevrez 1UP de ma part :-D
Les gens @YesThatIsMyName publient souvent des questions demandant une réponse dans un outil spécifique simplement parce qu'ils ne savent pas mieux. Restreindre les réponses uniquement à l'outil qu'ils ont demandé (à moins qu'ils ne soient très précis qu'ils ne peuvent utiliser que cet outil) alors qu'il existe une meilleure solution utilisant un autre outil n'est pas utile. Dans ce cas, sed et awk sont tous deux des outils standard qui existent dans chaque installation UNIX et les gens se demandent souvent lequel d'entre eux utiliser pour quelle tâche, il est donc très courant que les gens demandent une solution en 1 et acceptent une solution dans l'autre. .
@EdMorton Merci pour l'explication détaillée.
sed
sed -E '/^\/\/test$/,/^\/\/endtest/{/^\/\/(end)?test$/!d;}'
Comme /
est utilisé pour lier des regex, ils doivent être échappés, dans regex .
Si vous souhaitez conserver des marques (comme demandé):
sed '/^\/\/test$/,/^\/\/endtest/{/^\/\/\(end\)\{0,1\}test$/!d;}'
Explication:
Jetez un œil à info sed
, recherchez sed address
-> Regexp Addresses
et Adresses de plage
.
Entouré de {...}
, le symbole //
signifie n'importe quelle limite. P >
L'expression régulière vide '//' répète le dernier régulier correspondance d'expression (il en va de même si l'expression régulière vide est passé à la commande 's').
!
signifie pas
, puis d
pour supprimer la ligne
Alternative: Vous pouvez écrire:
sed -E '/^\/\/(end)?test$/,//{//!d}'
ou
sed '/^\/\/\(end\)\?test$/,//{//!d}'
Fonctionnera de la même manière, mais attention, cela pourrait inverser l'effet si un motif supplémentaire // endtest
peut exister avant premier motif ouvert ( // test
).
... Tout cela a été fait, en utilisant GNU sed
4.4 !
sed
Sous MacOS, j'ai supprimé avec succès les lignes recherchées avec cette syntaxe:
sed '/^\/\/test$/,/^\/\/endtest/{//!d}'
obtenir l'erreur ci-dessous stackoverflow.com/users/1765658/f-hauri sed '/ ^ \ / \ / test $ /, / ^ \ / \ / endtest / {//! d} 'test.txt sed: mauvaise expression régulière' ': (sous) expression vide
Quelle version de sed
(et OS) utilisez-vous?
si vos données sont dans le fichier 'd', essayez gnu sed:
sed -E '/\/\/test/,/\/\/endtest/{/\/\/.*test/!d}' d
voir aussi Comment sélectionner des lignes entre deux motifs?
Si
awk
est une alternative viable pour vous, vous devriez vérifier cette réponse que j'ai écrite il y a quelque temps: stackoverflow.com/ a / 31112076/42580N'utilisez pas d'expressions de plage car elles rendent les tâches triviales très légèrement plus brèves, mais nécessitent une réécriture complète ou du code en double lorsque vos exigences changent le moins du monde (par exemple pour tester une valeur à l'intérieur de la plage ou inclure / exclure les lignes de début / fin de plage) . Utilisez plutôt une variable d'indicateur. Étant donné que sed n'a pas de variables, vous ne devriez pas utiliser sed pour des tâches comme celle-ci, utilisez simplement awk à la place, voir par exemple stackoverflow. com / a / 55721516/1745001 .