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
%
seleccione todas las líneass
reemplazarx
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
#Linux
sed -i""
y
#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 .