comando sed con la opción -i falla en Mac, pero funciona en Linux

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 pruebo en mi Mac OS X, obtengo:

“comando c espera \ seguido de texto”

Pensé que mi Mac ejecuta 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 puedo replicar este comando en BSD sed ?

EDITAR:

Aquí hay un ejemplo real que causa esto:

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

Si usa la opción -i, debe proporcionar una extensión para sus copias de seguridad.

Si usted tiene:

 File1.txt File2.cfg 

El comando (tenga en cuenta 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' * 

crea 2 archivos de respaldo como:

 File1.txt.original File2.cfg.original 

No existe una forma portátil de evitar hacer copias de seguridad de archivos 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 -e copias de seguridad
  • sed -i'' -e ... – no funciona en OS X 10.6 pero funciona en 10.9+
  • sed -i '' -e ... – no funciona en GNU

Creo que en OS X cuando usa -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 de sed de GNU y BSD:

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

o con copia de seguridad:

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

¡Nota falta de espacio después de la opción -i ! (Necesario para GNU sed)

O bien, puede instalar la versión de GNU de sed en su Mac, llamada gsed, y usarla usando la syntax estándar de Linux.

Para eso, instale gsed usando ports (si no lo tiene, sudo port install gsed en http://www.macports.org/ ) ejecutando sudo port install gsed . Luego, puede ejecutar sed -i 's/old_link/new_link/g' *

Tuve el mismo problema en Mac y lo resolvió con brew :

 brew install gnu-sed 

y usar como

 gsed SED_COMMAND 

también puedes configurar set sed como alias a gsed (si quieres):

 alias sed=gsed 

La respuesta de Sinetris es correcta, pero uso esto con el comando 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.

Tu Mac sí ejecuta un shell BASH, pero esto es más una cuestión de qué implementación de sed estás tratando. En una Mac, sed proviene de BSD y es sutilmente diferente del sed que puede encontrar en una caja típica de Linux. Te sugiero que seas man sed .

A continuación, le mostramos cómo aplicar variables de entorno al archivo de plantilla (no es necesario hacer una copia de seguridad).

1. Crea una plantilla con {{FOO}} para reemplazarla más tarde.

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

2. Reemplace {{FOO}} con la variable FOO y la salida al nuevo archivo foo.conf

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

Trabajando tanto con macOS 10.12.4 como con Ubuntu 14.04.5

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

Funciona tanto en BSD como en Linux

Como indican las otras respuestas, no hay una forma de utilizar sed portable en OS X y Linux sin hacer copias de seguridad. Por lo tanto, en su lugar usé este Ruby one-liner para hacerlo:

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

En mi caso, tuve que llamarlo desde una tarea de rake (es decir, dentro de un script de Ruby), así que utilicé este nivel adicional de cotización:

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