¿Existe una invocación de sed
edición in situ sin copias de seguridad que funcione tanto en Linux como en Mac? Si bien el BSD sed
enviado con OS X parece necesitar sed -i '' …
, las sed
distribuciones GNU Linux generalmente vienen con interpreta las comillas como un nombre de archivo de entrada vacío (en lugar de la extensión de copia de seguridad), y necesita en su sed -i …
lugar.
¿Existe alguna sintaxis de línea de comando que funcione con ambos tipos, por lo que puedo usar el mismo script en ambos sistemas?
Respuestas:
Si realmente quiere usar
sed -i
la forma 'fácil', lo siguiente FUNCIONA tanto en GNU como en BSD / Macsed
:Tenga en cuenta la falta de espacio y el punto.
Prueba:
Obviamente, podría simplemente eliminar los
.bak
archivos.fuente
sed
)sed
no acepta una posicióncommand
argumento cuando se invoca con-i
- que debe ser suministrado con otra bandera,-e
. Por lo tanto, el comando se convierte en:sed -i.bak -e 's/foo/bar/' filename
sed -i.bak 's/foo/bar/' file && rm file.bak
Esto funciona con GNU sed, pero no en OS X:
Esto funciona en OS X, pero no con GNU sed:
En OS X usted
sed -i -e
ya que la extensión del archivo de respaldo se establecería en-e
sed -i'' -e
por las mismas razones: necesita un espacio entre-i
y''
.fuente
-i
y-i''
son idénticos en el tiempo de análisis de shell;sed
no puede comportarse de manera diferente en esas dos primeras invocaciones, porque obtiene exactamente los mismos argumentos.Cuando estoy en OSX, siempre instalo la versión de GNU sed a través de Homebrew, para evitar problemas en los scripts, porque la mayoría de los scripts fueron escritos para versiones de GNU sed.
Entonces su BSD sed será reemplazado por GNU sed.
Alternativamente, puede instalar sin nombres predeterminados, pero luego:
PATH
como se indica después de instalargnu-sed
gsed
osed
dependiendo de su sistemafuente
--with-default-names
fue retirado de homebrew núcleos , más información en esta respuesta. al instalargnu-sed
ahora, las instrucciones de instalación especifican que necesita agregargnubin
a suPATH
:PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"
Como Noufal Ibrahim pregunta, ¿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 podrían 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 ,
y esto parece una mejor solución en casi cualquier caso que los scripts, los alias u otras soluciones para tratar la incompatibilidad fundamental
sed -i
entre GNU / Linux y BSD / Mac.fuente
perl
es parte de la especificación de Linux Standard Base desde el 1 de mayo de 2009. refspecs.linuxfoundation.org/LSB_4.0.0/LSB-Languages/…No hay forma de que funcione.
Una forma es usar un archivo temporal como:
Esto funciona en ambos
fuente
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 que
file-e
aparecía "al azar" en mis directorios).Aparentemente no hay forma de
sed -i
trabajar de manera consistente tanto en MacOS como en Linuces.Mi recomendación, por lo que vale, no es actualizar en el lugar
sed
(que tiene modos de falla complejos), sino generar nuevos archivos y cambiarles el nombre después. En otras palabras: evitar-i
.fuente
La
-i
opción no es parte de POSIX Sed . Un método más portátil sería usar Vim en modo Ex:%
seleccione todas las líneass
reemplazarx
guardar y cerrarfuente
Aquí hay otra versión que funciona en Linux y macOS sin usar
eval
y sin tener que eliminar archivos de copia de seguridad. Utiliza matrices Bash para almacenar lossed
parámetros, que es más limpio que usareval
:Esto no crea un archivo de copia de seguridad, ni un archivo con citas adjuntas.
fuente
sedi=(-i) && [ "$(uname)" == "Darwin" ] && sedi=(-i '')
sed "${sedi[@]}" -e 's/foo/bar/' target.file
La respuesta de Steve Powell es bastante correcta, al consultar la página MAN para sed en OSX y Linux (Ubuntu 12.04) destaca la incompatibilidad dentro del uso de sed 'in situ' en los dos sistemas operativos.
JFYI, no debería haber espacio entre el -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
y
Página de manual de sed OSX
Lo resolví en un script usando un comando alias'd y la salida del nombre del sistema operativo de ' uname ' dentro de un bash 'if'. Intentar almacenar cadenas de comandos dependientes del sistema operativo en variables fue impredecible 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 aquí .
fuente
Si necesita hacer
sed
in situ en unbash
script, y NO desea que el lugar resulte con archivos .bkp, y tiene una manera de detectar el sistema operativo (por ejemplo, usando ostype.sh ), - entonces El siguiente truco con elbash
shell incorporadoeval
debería funcionar:fuente
Puedes usar esponja. Sponge es un antiguo programa de Unix, que se encuentra en el paquete moreutils (tanto en ubuntu y probablemente debian, como en homebrew en mac).
Almacenará todo el contenido de la tubería, esperará hasta que la tubería esté cerrada (probablemente significa que el archivo de entrada ya está cerrado) y luego sobrescribirá:
Desde la página del manual :
fuente
Lo siguiente funciona para mí en Linux y OS X:
sed -i' ' <expr> <file>
por ejemplo, para un archivo que
f
contieneaaabbaaba
sed -i' ' 's/b/c/g' f
cede
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 la
bash
versión 4.3.11 bajo Ubuntu 14.04.4 y en la versión Mac 3.2.57 bajo OS X 10.11.4 El Capitan (Darwin 15.4.0).fuente
Me encontré con este problema. La única solución rápida fue reemplazar el sed en mac a la versión gnu:
fuente