linux macos sed bsd

indicador sed in-place que funciona tanto en Mac(BSD) como en Linux



macos (12)

Como pregunta Noufal Ibrahim , ¿por qué no puedes usar Perl? Cualquier Mac tendrá Perl, y hay muy pocas distribuciones de Linux o BSD que no incluyan alguna versión de Perl en el sistema base. Uno de los únicos entornos que en realidad podría carecer de Perl sería BusyBox (que funciona como GNU / Linux para -i , excepto que no se puede especificar una extensión de copia de seguridad).

Como recomienda ismail ,

Dado que Perl está disponible en todos lados, simplemente hago perl -pi -es,foo,bar,g target.file

y esto parece ser una mejor solución en casi cualquier caso que las secuencias de comandos, alias u otras soluciones para hacer frente a la incompatibilidad fundamental de sed -i entre GNU / Linux y BSD / Mac.

¿Existe una invocación de la edición in situ de sed todo sin copias de seguridad que funcione tanto en Linux como en Mac? Mientras que el BSD sed embarcado con OS X parece necesitar sed -i '''' … , las distribuciones GNU sed Linux generalmente vienen con interpretaciones de citas como nombre de archivo de entrada vacío (en lugar de la extensión de respaldo), y necesita sed -i … lugar.

¿Hay alguna sintaxis en la línea de comandos que funcione con ambos sabores, por lo que puedo usar el mismo script en ambos sistemas?


Cuando estoy en OSX, siempre instalo la versión de GNU sed a través de Homebrew, para evitar problemas en las secuencias de comandos, porque la mayoría de las secuencias de comandos se escribieron para las versiones de GNU sed.

brew install gnu-sed --with-default-names

Entonces su BSD sed será reemplazada por GNU sed.

Alternativamente, puede instalar sin nombres predeterminados, pero luego:

  • Cambie su RUTA según las instrucciones después de instalar gnu-sed
  • Verifique sus scripts para elegir entre gsed o sed dependiendo de su sistema

Esto funciona con GNU sed, pero no con OS X:

sed -i -e ''s/foo/bar/'' target.file sed -i'''' -e ''s/foo/bar/'' target.file

Esto funciona en OS X, pero no con GNU sed:

sed -i '''' -e ''s/foo/bar/'' target.file

En OS X usted

  • no se puede usar sed -i -e ya que la extensión del archivo de respaldo se establecería en -e
  • no se puede usar sed -i'''' -e por las mismas razones, necesita un espacio entre -i y '''' .

La opción -i no es parte de POSIX Sed . Un método más portátil sería usar Vim en modo Ex:

ex -sc ''%s/alfa/bravo/|x'' file

  1. % seleccione todas las líneas

  2. s reemplazar

  3. x guardar y cerrar


Lo siguiente me funciona en Linux y OS X:

sed -i'' '' <expr> <file>

por ejemplo, para un archivo f contiene aaabbaaba

sed -i'' '' ''s/b/c/g'' f

produce aaaccaaca tanto en Linux como en Mac. Tenga en cuenta que hay una cadena entre comillas que contiene un espacio , sin espacio entre -i y la cadena. Las comillas simples o dobles funcionan.

En Linux estoy usando bash versión 4.3.11 bajo Ubuntu 14.04.4 y en Mac versión 3.2.57 bajo OS X 10.11.4 El Capitan (Darwin 15.4.0).


Me encontré con este problema. La única solución rápida fue reemplazar sed en mac a la versión gnu:

brew install gnu-sed


No hay forma de que funcione.

Una forma es usar un archivo temporal como:

TMP_FILE=`mktemp /tmp/config.XXXXXXXXXX` sed -e "s/abc/def/" some/file > $TMP_FILE mv $TMP_FILE some/file

Esto funciona en ambos


Puedes usar esponja. Sponge es un antiguo programa de Unix, que se encuentra en el paquete moreutils (tanto en ubuntu como probablemente en debian, y en homebrew en mac).

Búfer todo el contenido de la tubería, espere hasta que la tubería esté cerca (lo que probablemente significa que el archivo de entrada ya está cerca) y luego sobrescriba:

Desde la página man :

Sinopsis

sed ''...'' archivo | grep ''...'' | archivo de esponja


Si necesita sed en un script bash , y NO quiere que el in-place resulte con archivos .bkp, y tiene una forma de detectar el sistema ostype.sh (por ejemplo, usando ostype.sh ), - entonces debería funcionar el siguiente truco con la eval incorporada de shell bash :

OSTYPE="$(bash ostype.sh)" cat > myfile.txt <<"EOF" 1111 2222 EOF if [ "$OSTYPE" == "osx" ]; then ISED=''-i ""'' else # $OSTYPE == linux64 ISED=''-i""'' fi eval sed $ISED ''s/2222/bbbb/g'' myfile.txt ls # GNU and OSX: still only myfile.txt there cat myfile.txt # GNU and OSX: both print: # 1111 # bbbb # NOTE: # if you just use `sed $ISED ''s/2222/bbbb/g'' myfile.txt` without `eval`, # then you will get a backup file with quotations in the file name, # - that is, `myfile.txt""`


Si realmente quiere usar sed -i la manera ''fácil'', lo siguiente SÍ funciona tanto en sed GNU como en BSD / Mac:

sed -i.bak ''s/foo/bar/'' filename

Tenga en cuenta la falta de espacio y el punto.

Prueba:

# GNU sed % sed --version | head -1 GNU sed version 4.2.1 % echo ''foo'' > file % sed -i.bak ''s/foo/bar/'' ./file % ls file file.bak % cat ./file bar # BSD sed % sed --version 2>&1 | head -1 sed: illegal option -- - % echo ''foo'' > file % sed -i.bak ''s/foo/bar/'' ./file % ls file file.bak % cat ./file bar

Obviamente, podrías eliminar los archivos .bak .


Respuesta: No.

La respuesta originalmente aceptada en realidad no hace lo que se solicita (como se señala en los comentarios). (Encontré esta respuesta cuando busqué la razón por la cual un file-e aparecía "aleatoriamente" en mis directorios).

Aparentemente, no hay forma de que sed -i funcione de manera consistente tanto en MacOS como en Linuces.

Mi recomendación, por lo que vale, no es actualizar en el lugar con sed (que tiene modos de falla complejos), sino generar nuevos archivos y cambiarles el nombre después. En otras palabras: evita -i .


La respuesta de Steve Powell es bastante correcta, consultar la página MAN para sed en OSX y Linux (Ubuntu 12.04) resalta la compatibilidad en el uso de sed ''in situ'' en los dos sistemas operativos.

JFYI, no debería haber espacio entre la -i y las comillas (que denotan una extensión de archivo vacía) usando la versión Linux de sed, por lo tanto

sed Linux Man Page

#Linux sed -i""

y

página de sed OSX Man

#OSX (notice the space after the ''-i'' argument) sed -i ""

Entendí esto en un script usando un comando alias y el resultado del nombre del sistema operativo de '' uname '' dentro de un bash ''if''. Intentar almacenar cadenas de comandos dependientes del sistema operativo en variables fue al azar al interpretar las comillas. El uso de '' shopt -s expand_aliases '' es necesario para expandir / usar los alias definidos en su script. el uso de shopt se trata here .