El comando sed con la opción-i falla en Mac, pero funciona en Linux
macos bash (11)
He utilizado con éxito el siguiente comando sed
para buscar / reemplazar texto en Linux:
sed -i ''s/old_link/new_link/g'' *
Sin embargo, cuando lo intento en mi Mac OS X, obtengo:
"el comando c espera / seguido de texto"
Pensé que mi Mac tiene un shell BASH normal. ¿Que pasa?
EDITAR:
De acuerdo con @High Performance, esto se debe a que Mac sed
un sabor diferente (BSD), por lo que mi pregunta sería, ¿cómo replicar este comando en BSD sed
?
EDITAR:
Aquí hay un ejemplo real que causa esto:
sed -i ''s/hello/gbye/g'' *
Aquí se explica cómo aplicar las variables de entorno al archivo de plantilla (sin necesidad de copia de seguridad).
1. Cree una plantilla con {{FOO}} para reemplazar más tarde.
echo "Hello {{FOO}}" > foo.conf.tmpl
2. Reemplace {{FOO}} con la variable FOO y realice la salida al nuevo archivo foo.conf
FOO="world" && sed -e "s/{{FOO}}/$FOO/g" foo.conf.tmpl > foo.conf
Trabajando tanto macOS 10.12.4 como Ubuntu 14.04.5
Como lo indican las otras respuestas, no hay una forma de usarlo de manera portátil en OS X y Linux sin hacer copias de respaldo. Entonces, en lugar de eso utilicé este Ruby one-liner para hacerlo:
ruby -pi -e "sub(/ $/, '''')" ./config/locales/*.yml
En mi caso, necesitaba llamarlo desde una tarea de rake
(es decir, dentro de un script de Ruby), así que usé este nivel adicional de cotización:
sh %q{ruby -pi -e "sub(/ $/, '''')" ./config/locales/*.yml}
Creo que en OS X cuando se utiliza -i se requiere una extensión para los archivos de copia de seguridad. Tratar:
sed -i .bak ''s/hello/gbye/g'' *
Usando GNU sed
la extensión es opcional .
Esto funciona con las versiones GNU y BSD de sed:
sed -i'''' -e ''s/old_link/new_link/g'' *
o con copia de seguridad:
sed -i''.bak'' -e ''s/old_link/new_link/g'' *
Tenga en cuenta que falta espacio después de la opción -i
! (Necesario para GNU sed)
He creado una función para manejar la diferencia entre MacOS (probado en MacOS 10.12) y otro sistema operativo:
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
}
Uso:
$(replace_in_file ''s,MASTER_HOST.*,MASTER_HOST=''"$MASTER_IP"'','' "./mysql/.env")
Dónde:
es un delimitador
''s,MASTER_HOST.*,MASTER_HOST=''"$MASTER_IP"'',''
es un patrón
"./mysql/.env"
es la ruta al archivo
La respuesta de Sinetris es correcta, pero uso esto con el comando de find
para ser más específico sobre qué archivos quiero cambiar. En general, esto debería funcionar (probado en osx /bin/bash
):
find . -name "*.smth" -exec sed -i '''' ''s/text1/text2/g'' {} /;
En general cuando se usa sed
sin find
en proyectos complejos es menos eficiente.
O bien, puede instalar la versión GNU de sed en su Mac, llamada gsed, y usarla usando la sintaxis estándar de Linux.
Para eso, instale gsed
usando puertos (si no lo tiene, consígalo en http://www.macports.org/ ) ejecutando sudo port install gsed
. Luego, puede ejecutar sed -i ''s/old_link/new_link/g'' *
Si utiliza la opción -i, debe proporcionar una extensión para sus copias de seguridad.
Si usted tiene:
File1.txt
File2.cfg
El comando (note la falta de espacio entre -i
y ''''
y el -e
para que funcione en las nuevas versiones de Mac y en GNU):
sed -i''.original'' -e ''s/old_link/new_link/g'' *
crear 2 archivos de copia de seguridad como:
File1.txt.original
File2.cfg.original
No hay una forma portátil de evitar la creación de archivos de copia de seguridad porque es imposible encontrar una combinación de comandos sed que funcione en todos los casos:
-
sed -i -e ...
- no funciona en OS X ya que crea copias de seguridad-e
-
sed -i'''' -e ...
- no funciona en OS X 10.6 pero funciona en 10.9+ -
sed -i '''' -e ...
- no funciona en GNU
Su Mac sí ejecuta un shell BASH, pero esta es más una cuestión de con qué implementación de sed está tratando. En una Mac sed proviene de BSD y es sutilmente diferente de la sed que puede encontrar en una caja de Linux típica. Te sugiero que te man sed
Tuvo el mismo problema en Mac y lo resolví con brew
:
brew install gnu-sed
y usar como
gsed SED_COMMAND
puede establecer tan bien como sed
como alias a gsed
(si lo desea):
alias sed=gsed
sed -ie ''s/old_link/new_link/g'' *
Funciona tanto en BSD como en Linux