linux macos bash sed

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