la commande sed avec l'option-i (édition en place) fonctionne très bien sur Ubuntu mais pas sur Mac [dupliquer]
cette question a déjà une réponse ici:
Je ne sais rien sur Sed mais j'ai besoin de cette commande (qui fonctionne très bien sur Ubuntu) pour travailler sur un Mac OSX:
sed -i "/ $domain .*#drupalpro/d" /etc/hosts
j'obtiens:
sed: 1: "/etc/hosts": extra characters at the end of h command
4 réponses
Navires Ubuntu avec GNU sed
, où le suffixe pour l'option -i
est facultatif. OS X est livré avec BSD sed
, où le suffixe est obligatoire. Essayez sed -i ''
À compléter", 1519480920" microtherion de l'utile, du point de réponse :
- avec une solution portable
- avec des informations de fond
tl; dr :
l'équivalent de ce GNU sed
(standard sur la plupart Linux distros) commande:
sed -i 's/foo/bar/' file
est ce BSD / macOS sed
commande:
sed -i '' 's/foo/bar/' file # Note the '' as a *separate argument*
Avec BSD/macOS sed
, les commandes suivantes faire pas travail ou pas comme prévu:
sed -i 's/foo/bar/' file # Breaks; script is misinterpreted as backup-file suffix
sed -i'' 's/foo/bar/' file # Ditto
sed -i -e 's/foo/bar/' file # -e is misinterpreted as backup-file suffix
pour une discussion de tous le les différences entre GNU sed
et BSD/mac os sed
, voir cette réponse de la mine.
Portable "approche de 1519590920" :
Note: Portable signifie ici que la commande fonctionne avec les deux implémentations discutées. Il n'est pas portable dans un POSIX sens, parce que l'option -i
n'est pas conforme POSIX .
# Works with both GNU and BSD/macOS Sed, due to a *non-empty* option-argument:
# Create a backup file *temporarily* and remove it on success.
sed -i.bak 's/foo/bar/' file && rm file.bak
pour une explication, voir ci-dessous; pour les solutions de rechange, y compris une solution conforme à POSIX, voir cette réponse connexe de la mienne.
informations générales
In GNU sed
(standard sur la plupart des distributions Linux) et BSD / macOS sed
, les -i
option, qui exécute mise à jour en place [1]
de ses fichiers d'entrée, accepte une option-argument qui spécifie ce que suffixe (extension de nom de fichier) à utiliser pour le fichier de sauvegarde du fichier mis à jour .
par exemple, dans les deux implémentations , ce qui suit conserve le fichier original, file
, comme fichier de sauvegarde file.bak
:
sed -i.bak 's/foo/bar/' file # Keep original as 'file.bak'; NO SPACE between -i and .bak
même si avec GNU sed
le suffixe argument est optionnel , alors qu'avec BSD/macOS "1519640920 sed
il est obligatoire , la syntaxe ci-dessus fonctionne avec à la fois implémentations, parce que directement attenant l'option-argument ( .bak
) à l'option ( -i
) - -i.bak
, par opposition à -i .bak
- fonctionne à la fois comme un facultatif et un obligatoire option-argument :
- syntaxe
-i.bak
est le seulement forme qui fonctionne pour un optionnel option-argument. - syntaxe
-i.bak
aussi fonctionne comme un obligatoire option-argument, comme un alternative à-i .bak
, c'est à dire, en spécifiant l'option et son argument séparément .
ne spécifiant pas de suffixe - ce qui est souvent le cas - signifie que pas de fichier de sauvegarde doit être conservé, et c'est où l'incompatibilité se pose :
-
avec GNU
sed
, ne pas spécifier de suffixe signifie simplement utiliser-i
par lui-même . -
avec BSD / macOS
sed
, sans suffixe signifie la chaîne vide comme suffixe-obligatoire, et pour technique " argument : c'est-à-dire,-i ''
pas-i''
.
-i''
ne fonctionne pas, car à sed
il est impossible de le distinguer de juste -i
, parce que le shell effectivement supprime les citations vides (il concaténate -i
et ''
et supprime les citations avec la fonction syntaxique), et passe juste -i
dans les deux cas.
avec (effectivement) juste -i
spécifié, c'est le suivant argument qui est interprété comme l'option-argument:
sed -i 's/foo/bar/' file # BREAKS with BSD/macOS Sed
's/foo/bar/'
- destiné au sed script (commande) - est maintenant interprété comme le suffixe , et le mot file
est interprété comme le script.
L'interprétation d'un tel mot comme script conduit alors à un message d'erreur obscur tel que
sed: 1: "file": invalid command code f
,
parce que le f
est interprété comme une commande Sed (fonction).
de même, avec:
sed -i -e 's/foo/bar/' file # CREATES BACKUP FILE 'file-e'
-e
est interprété comme le suffixe argument, et non comme -e
option de Sed (qui peut être utilisé pour spécifier multiple commandes, si nécessaire).
En conséquence, au lieu de ne pas conserver de sauvegarde, vous obtenez un fichier de sauvegarde avec le suffixe -e
.
que cette commande ne fonctionne pas comme prévu est moins évident, parce que la mise à jour en place réussit, étant donné que la syntaxe l'exigence de l'argument du suffixe est satisfaite par l'argument -e
.
que la création accidentelle de ces fichiers de sauvegarde passe facilement inaperçue est l'explication la plus probable pour réponse incorrecte de Crt et cette réponse incorrecte à une question similaire ayant reçu tant de votes positifs (en date de cette écriture).
[1] à proprement parler, un le fichier temporaire est créé dans les coulisses, puis remplace le fichier original; cette approche peut être problématique: voir la moitié inférieure de cette réponse de la mienne.
l'homme est votre ami.
OS X
-i extension
Edit files in-place, saving backups with the specified extension.
If a zero-length extension is given, no backup will be saved. It
is not recommended to give a zero-length extension when in-place
editing files, as you risk corruption or partial content in situ-
ations where disk space is exhausted, etc.
dans OS X, vous pouvez utiliser la version GNU de sed: gsed
.
# if using brew
brew install gnu-sed
#if using ports
sudo port install gsed
alors, si votre script doit être portable, en fonction de votre système D'exploitation, vous pouvez définir quelle commande Utiliser.
SED=sed
unamestr=`uname`
if [[ "$unamestr" == "Darwin" ]] ; then
SED=gsed
type $SED >/dev/null 2>&1 || {
echo >&2 "$SED it's not installed. Try: brew install gnu-sed" ;
exit 1;
}
fi
# here your sed command, e.g.:
$SED -i "/ $domain .*#drupalpro/d" /etc/hosts