J'ai vu plusieurs réponses supprimer une seule ligne avec sed
ou grep
, mais j'ai besoin de rechercher une ligne, de supprimer celle-ci et les 2 lignes précédentes. Par exemple, dans le fichier ~/.profile
, j'ai des lignes comme celles-ci:
#Set environment variable
export NAME=value
# (blank line here)
Je voudrais donc rechercher #Set environment variable
, et le supprimer, puis supprimer la ligne suivante export NAME=variable
(le contenu ne devrait pas avoir d'importance), ainsi que la ligne vierge suivante. Les noms de variable export
sont dynamiques, mais le commentaire sera toujours le même. Il pourrait y avoir d’autres variables export
sans le commentaire ci-dessus, que je ne souhaite pas supprimer.
Comment puis-je accomplir cela?
Avec la nouvelle version de GNU sed
(fournie avec Ubuntu), vous pouvez reproduire les nouvelles lignes littéralement:
sed -z 's/#Set environment variable\nexport [^\n]\+\n\n//g' file.txt
L'option -z
traitera les lignes des fichiers d'entrée comme étant terminées par ASCII NUL plutôt que par une nouvelle ligne. Nous pouvons donc utiliser \n
pour faire correspondre les nouvelles lignes.
#Set environment variable\n
correspondra à la première ligne (avec la nouvelle ligne)
export [^\n]\+\n
correspondra à la deuxième ligne commençant par export
Comme la troisième ligne est vide, simplement \n
fera
Ensuite, nous remplaçons tout le motif associé au blanc pour conserver la portion désirée.
Dans vous voulez écraser le fichier avec le contenu modifié:
sed -zi.bak 's/#Set environment variable\nexport [^\n]\+\n\n//g' file.txt
Le fichier original sera conservé sous le nom file.txt.bak
, si vous ne voulez pas utiliser simplement sed -zi
.
Voici un test:
$ cat file.txt
#Set environment variable
export NAME=value
#some text
#Set environment variable
export NAME=value
check
value
export some=value
#Set environment variable
export NAME=value
foo bar
$ sed -z 's/#Set environment variable\nexport [^\n]\+\n\n//g' file.txt
#Set environment variable
export NAME=value
#some text
check
value
export some=value
foo bar
Il est très facile de faire cela avec la commande delete standard de sed:
cp ~/.profile ~/.profile.bak
sed '/#Set environment variable/,+2 d' <~/.profile.bak >~/.profile
Soyez prudent avec votre ~/.profile
Bien que votre question donne l’impression que vous cherchez un moyen de le faire en ligne de commande, si j’étais dans votre situation et que je ne voulais le faire que pour un ou deux fichiers, j’utiliserais emacs
.
emacs
a la capacité d'apprendre une séquence de frappes au clavier, puis de les répéter autant de fois que vous le souhaitez. Donc, dans votre cas, je voudrais ouvrir ~/.profile
dans emacs
et puis tapez
C-x ( C-s #Set environment variable C-a C-k C-k C-k C-x )
[qui, en mots, fait ceci: Cx (signifie "commence à apprendre cela"; Cs signifie "recherche de", alors nous recherchons la variable d'environnement #Set, puis Ca signifie "retour au début de la ligne, et le trois Ck signifie "supprimer cette ligne", et enfin Cx) signifie "arrêtez d'apprendre cela".]
Après avoir tapé ces commandes une fois, emacs a supprimé trois lignes, mais il a également appris à le faire par cœur. Vous pouvez donc taper
C-x e
et il le fera encore, ou
C-u 100 C-x e
et il le fera 100 fois (ou s’arrêtera quand il ne trouvera plus de lignes avec "# variable d’environnement" dans).
L'avantage d'utiliser emacs est que vous pouvez voir vos modifications se faire "en direct", et pour une personne paranoïaque comme moi qui a peur qu'un seul type de frappe puisse supprimer beaucoup de choses que je ne voulais pas effacer, cela me rend beaucoup plus heureux [ Dès que les choses tournent mal dans emacs, vous pouvez simplement revenir en arrière et les corriger avec C-_
].