linux macos sed bsd inplace-editing

linux - El comando sed con la opción-i(edición in situ) funciona bien en Ubuntu, pero no en Mac



macos bsd (4)

En OS X, puede usar la versión GNU de sed: gsed .

# if using brew brew install gnu-sed #if using ports sudo port install gsed

Entonces, si su script debe ser portable, dependiendo de su sistema operativo, puede definir qué comando usar.

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

No sé nada de Sed, pero necesito este comando (que funciona bien en Ubuntu) para trabajar en Mac OSX:

sed -i "/ $domain .*#drupalpro/d" /etc/hosts

Me estoy poniendo:

sed: 1: "/etc/hosts": extra characters at the end of h command


Para complementar la respuesta útil y precisa de microtherion :

  • con una solución portátil
  • con información de fondo

tl; dr :

El equivalente de este comando GNU sed (estándar en la mayoría de las distros Linux ):

sed -i ''s/foo/bar/'' file

es este comando BSD / macOS sed :

sed -i '''' ''s/foo/bar/'' file # Note the '''' as a *separate argument*

Con BSD / macOS sed , los siguientes comandos no funcionan del todo o no como se esperaba:

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

Para una discusión de todas las diferencias entre GNU sed y BSD / macOS sed , vea esta respuesta mía.

Enfoque portátil :

Nota: Portátil aquí significa que el comando funciona con ambas implementaciones discutidas. No es portátil en un sentido POSIX , porque la opción -i no es compatible con 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

Para una explicación, mira a continuación; para soluciones alternativas, incluyendo una que cumpla con POSIX, vea esta respuesta relacionada mía.

Información de fondo

En GNU sed (estándar en la mayoría de las distribuciones de Linux) y BSD / macOS sed , la opción -i , que realiza la actualización in situ [1] de sus archivos de entrada, acepta una opción-argumento que especifica qué sufijo (extensión de nombre de archivo) usar para el archivo de copia de seguridad del archivo que se está actualizando .

Por ejemplo, en ambas implementaciones, lo siguiente mantiene el archivo original, file , como archivo de respaldo file.bak :

sed -i.bak ''s/foo/bar/'' file # Keep original as ''file.bak''; NO SPACE between -i and .bak

Aunque con GNU sed el argumento de sufijo es opcional , mientras que con BSD / macOS sed es obligatorio , la sintaxis anterior funciona con ambas implementaciones, ya que directamente junto al argumento de opción ( .bak ) a la opción ( -i ) - -i.bak , a diferencia de -i .bak - funciona como opción-argumento opcional y obligatorio :

  • Sintaxis -i.bak es la única forma que funciona para una opción opcional -argumento.
  • La sintaxis -i.bak también funciona como un argumento-opción obligatorio , como una alternativa a -i .bak , es decir, especificando la opción y su argumento por separado .

No especificar un sufijo , que a menudo es el caso, significa que no se debe guardar ningún archivo de copia de seguridad , y es allí donde surge la incompatibilidad :

  • Con GNU sed , no especificar un sufijo significa simplemente usar -i solo .

  • Con BSD / macOS sed , no especificar un sufijo significa especificar la cadena vacía como el sufijo - obligatorio - y, por razones técnicas , la cadena vacía solo se puede pasar como un argumento separado : es decir, -i '''' no -i'''' .

-i'''' no funciona, porque para sed es indistinguible de solo -i , porque el shell efectivamente elimina las comillas vacías (concatena -i y '''' y elimina las comillas con función sintáctica), y pasa solo -i en ambos casos.

Con (efectivamente) solo -i especificado, es el siguiente argumento que se interpreta como el argumento de opción:

sed -i ''s/foo/bar/'' file # BREAKS with BSD/macOS Sed

''s/foo/bar/'' - destinado a la secuencia de comandos de Sed (comando) - ahora se interpreta como el sufijo , y el file palabra se interpreta como la secuencia de comandos.
Interpretar tal palabra como script conduce a un mensaje de error oscuro como
sed: 1: "file": invalid command code f ,
porque f se interpreta como un comando Sed (función).

Del mismo modo, con:

sed -i -e ''s/foo/bar/'' file # CREATES BACKUP FILE ''file-e''

-e se interpreta como el argumento de sufijo , y NO como la opción -e de Sed (que se puede usar para especificar varios comandos, si es necesario).
Como resultado, en lugar de no mantener ninguna copia de seguridad, obtiene un archivo de copia de seguridad con el sufijo -e .

El hecho de que este comando no funcione como está previsto es menos obvio, porque la actualización in situ tiene éxito, dado que el argumento -e satisface el requisito de sintaxis del argumento de sufijo.

Que la creación accidental de estos archivos de copia de seguridad pase desapercibida es la explicación más probable para la respuesta incorrecta de Crt y esta respuesta incorrecta a una pregunta similar que recibió tantas votaciones (a partir de este escrito).

[1] Estrictamente hablando, se crea un archivo temporal detrás de escena que luego reemplaza el archivo original; este enfoque puede ser problemático: ver la mitad inferior de esta respuesta mía.


Ubuntu se envía con GNU sed , donde el sufijo para la opción -i es opcional. OS X se envía con BSD sed , donde el sufijo es obligatorio. Prueba sed -i ''''


el hombre es tu amigo

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.