207 votes

Modifications sur place avec sed sous OS X

J'aimerais éditer un fichier avec sed sous OS X. J'utilise la commande suivante :

sed 's/oldword/newword/' file.txt

La sortie est envoyée au terminal. fichier.txt n'est pas modifié. Les changements sont enregistrés dans fichier2.txt avec cette commande :

sed 's/oldword/newword/' file1.txt > file2.txt

Cependant, je ne veux pas d'un autre dossier. Je veux juste éditer fichier1.txt . Comment faire ?

J'ai essayé l'option -i. Il en résulte l'erreur suivante :

sed: 1: "file1.txt": invalid command code f

3 votes

Quelle est la commande exacte que vous utilisez lorsque vous essayez la commande -i drapeau ?

379voto

whittle Points 574

Vous pouvez utiliser le -i en lui fournissant un suffixe à ajouter au fichier sauvegardé. Extension de l'exemple :

sed -i.bu 's/oldword/newword/' file1.txt

Vous obtiendrez deux fichiers : l'un portant le nom file1.txt qui contient la substitution, et une autre portant le nom de file1.txt.bu qui contient le contenu original.

Légèrement dangereux

Si vous voulez écraser le fichier original de manière destructive, utilisez quelque chose comme :

sed -i '' 's/oldword/newword/' file1.txt
      ^ note the space

En raison de la manière dont la ligne est analysée, un espace est nécessaire entre le drapeau d'option et son argument. car l'argument est de longueur nulle.

À part la possibilité de détruire votre original, je ne connais pas d'autres dangers à piéger sed de cette façon. Il faut cependant noter que si cette invocation de sed fait partie d'un script, The Unix Way™ serait (IMHO) d'utiliser sed de manière non destructive, vérifiez qu'il se termine proprement, puis supprimez le fichier superflu.

0 votes

Vous avez raison, j'ai omis l'extension après l'option -i. Est-ce que -i'' dangereux pour une raison autre que la possibilité d'endommager le fichier original (et de ne pas avoir de copie de sauvegarde) ?

0 votes

Selon la sed Si vous manquez d'espace disque sur l'appareil, vous risquez de corrompre un fichier à mi-parcours et d'obtenir un mauvais résultat. Si vous travaillez sous un contrôle de source local sed -i "" sans sauvegardes devrait suffire la plupart du temps (ou simplement git init && git add -A . && git commit -m 'backup' avant d'exécuter sed dans -i ).

5 votes

J'ai trouvé la partie "légèrement dangereuse" particulièrement utile. +1

28voto

jkukul Points 1930

En -i ne fonctionne probablement pas pour vous, car vous avez suivi un exemple pour le drapeau GNU sed tandis que macOS utilise BSD sed et leur syntaxe est légèrement différente.

Toutes les autres réponses vous indiquent comment corriger la syntaxe pour qu'elle fonctionne avec sed BSD. L'alternative est d'installer GNU sed sur votre macOS avec :

brew install gsed

et l'utiliser à la place du sed livrée avec macOS (notez le g préfixe), par exemple

gsed -i 's/oldword/newword/' file1.txt

Si vous souhaitez que les commandes GNU sed soient toujours portables sur votre macOS, vous pouvez ajouter le répertoire "gnubin" à votre chemin d'accès, en ajoutant quelque chose comme ceci à votre fichier .bashrc / .zshrc (exécuter brew info gsed pour savoir ce qu'il faut faire exactement) :

export PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"

et à partir de ce moment-là, le sed GNU devient votre sed par défaut et vous pouvez simplement exécuter :

sed -i 's/oldword/newword/' file1.txt

27voto

ksnt Points 21

J'ai le même problème avec MacOS

sed -i '' 's/oldword/newword/' file1.txt

ne fonctionne pas, mais

sed -i"any_symbol" 's/oldword/newword/' file1.txt

fonctionne bien.

2 votes

C'est maintenant l'inverse qui se produit. sed -i '' <file> fonctionne mais sed -i'' <file> ne fonctionne plus

10voto

jazzed Points 342
sed -i -- "s/https/http/g" file.txt

4voto

kenorb Points 2464

Vous pouvez utiliser -i'' ( --in-place ) pour sed comme cela a déjà été suggéré. Voir : En -i argument en lieu et place Toutefois, il convient de noter que -i est une extension non standard de FreeBSD et peut ne pas être disponible sur d'autres systèmes d'exploitation. Deuxièmement sed est un S tream ED itor, pas un éditeur de fichiers .


L'autre solution consiste à utiliser la substitution intégrée dans le mode Ex de Vim, comme par exemple :

$ ex +%s/foo/bar/g -scwq file.txt

et pour les fichiers multiples :

$ ex +'bufdo!%s/foo/bar/g' -scxa *.*

Pour éditer tous les fichiers de manière récursive, vous pouvez utiliser **/*.* si l'interpréteur de commandes le permet (activé par shopt -s globstar ).


Une autre solution consiste à utiliser gawk et sa nouvelle "Extension "inplace par exemple :

$ gawk -i inplace '{ gsub(/foo/, "bar") }; { print }' file1

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X