web-dev-qa-db-fra.com

la commande sed avec l'option -i échouant sur Mac mais fonctionnant sous Linux

J'ai utilisé avec succès la commande sed suivante pour rechercher/remplacer du texte sous Linux:

sed -i 's/old_link/new_link/g' *

Cependant, lorsque je l'essaie sur mon Mac OS X, je reçois:

"la commande c attend\suivi d'un texte"

Je pensais que mon Mac fonctionnait sous BASH Shell. Quoi de neuf?

MODIFIER:

Selon @High Performance, cela est dû au fait que Mac sed a une saveur différente (BSD). Ma question est donc de savoir comment répliquer cette commande dans BSD sed.

MODIFIER:  

Voici un exemple concret qui provoque ceci:

sed -i 's/hello/gbye/g' *
231
Yarin

Si vous utilisez l'option -i, vous devez fournir une extension pour vos sauvegardes.

Si tu as:

File1.txt
File2.cfg

La commande (notez le manque d’espace entre -i et '' et le -e pour que cela fonctionne avec les nouvelles versions de Mac et GNU):

sed -i'.original' -e 's/old_link/new_link/g' *

créer 2 fichiers de sauvegarde comme:

File1.txt.original
File2.cfg.original

Il n'y a pas de moyen portable d'éviter de créer des fichiers de sauvegarde car il est impossible de trouver un mélange de commandes sed qui fonctionne dans tous les cas:

  • sed -i -e ... - ne fonctionne pas sous OS X car il crée des sauvegardes -e
  • sed -i'' -e ... - ne fonctionne pas sous OS X 10.6 mais fonctionne sous 10.9+
  • sed -i '' -e ... - ne fonctionne pas sous GNU

Note Etant donné qu'aucune commande sed ne fonctionne sur toutes les plateformes, vous pouvez essayer d'utiliser une autre commande pour obtenir le même résultat.

par exemple. Perl -i -pe's/old_link/new_link/g' *

322
Sinetris

Je pense que sur OS X, lorsque vous utilisez -i, une extension des fichiers de sauvegarde est obligatoire . Essayer:

sed -i .bak 's/hello/gbye/g' *

Avec GNU sed, l’extension est optionnel .

44
Dennis Williamson

Cela fonctionne avec les versions GNU et BSD de sed:

sed -i'' -e 's/old_link/new_link/g' *

ou avec sauvegarde:

sed -i'.bak' -e 's/old_link/new_link/g' *

Notez l'espace manquant après l'option -i! (Nécessaire pour GNU sed)

42
chipiik

Avait le même problème dans Mac et résolu avec brew:

brew install gnu-sed

et utiliser comme

gsed SED_COMMAND

vous pouvez également définir sed comme alias sur gsed (si vous le souhaitez):

alias sed=gsed
19
Sruthi Poddutur

Vous pouvez également installer la version GNU de sed sur votre Mac, appelée gsed, et l’utiliser à l’aide de la syntaxe Linux standard.

Pour cela, installez gsed en utilisant les ports (si vous ne l’avez pas, procurez-vous à http://www.macports.org/ ) en exécutant Sudo port install gsed. Ensuite, vous pouvez exécuter sed -i 's/old_link/new_link/g' *

14
Ohad Kravchick

La réponse de Sinetris est correcte, mais j'utilise la commande find pour préciser les fichiers à modifier. En général, cela devrait fonctionner (testé sur osx /bin/bash):

find . -name "*.smth" -exec sed -i '' 's/text1/text2/g' {} \;

En général, utiliser sed sans find dans des projets complexes est moins efficace.

8
Lucas

Votre Mac utilise effectivement un shell BASH, mais la question de la mise en œuvre de sed que vous utilisez est une question. Sur un Mac, sed provient de BSD et est légèrement différent de celui que vous pourriez trouver sur une machine Linux typique. Je vous suggère man sed.

7

Voici comment appliquer des variables d’environnement au fichier de modèle (aucune sauvegarde requise).

1. Créez un modèle avec {{FOO}} pour un remplacement ultérieur.

echo "Hello {{FOO}}" > foo.conf.tmpl

2. Remplacez {{FOO}} par la variable FOO et exportez-le dans le nouveau fichier foo.conf.

FOO="world" && sed -e "s/{{FOO}}/$FOO/g" foo.conf.tmpl > foo.conf

Travailler à la fois macOS 10.12.4 et Ubuntu 14.04.5

1
katopz
sed -ie 's/old_link/new_link/g' *

Fonctionne sur BSD et Linux

0
ashokrajar

Comme l’indiquent les autres réponses, il n’existe pas de moyen d’utiliser Sed sur OS X et Linux sans créer de fichiers de sauvegarde. J'ai donc utilisé à la place cette doublure Ruby:

Ruby -pi -e "sub(/ $/, '')" ./config/locales/*.yml

Dans mon cas, je devais l'appeler à partir d'une tâche rake (c'est-à-dire à l'intérieur d'un script Ruby). J'ai donc utilisé ce niveau supplémentaire de citation:

sh %q{Ruby -pi -e "sub(/ $/, '')" ./config/locales/*.yml}
0
dankohn

J'ai créé une fonction permettant de gérer la différence sed entre MacOS (testé sous MacOS 10.12) et un autre système d'exploitation:

OS=`uname`
# $(replace_in_file pattern file)
function replace_in_file() {
    if [ "$OS" = 'Darwin' ]; then
        # for MacOS
        sed -i '' -e "$1" "$2"
    else
        # for Linux and Windows
        sed -i'' -e "$1" "$2"
    fi
}

Usage:

$(replace_in_file 's,MASTER_Host.*,MASTER_Host='"$MASTER_IP"',' "./mysql/.env")

Où:

, est un délimètre

's,MASTER_Host.*,MASTER_Host='"$MASTER_IP"',' est un motif

"./mysql/.env" est le chemin du fichier

0
v.babak