El comando sed con la opción -i falla en Mac, pero funciona en Linux
Utilicé con éxito el siguiente sed
comando para buscar/reemplazar texto en Linux:
sed -i 's/old_link/new_link/g' *
Sin embargo, cuando lo pruebo en mi Mac OS X, aparece:
"el comando c espera \ seguido de texto"
Pensé que mi Mac ejecuta un shell BASH normal. ¿Qué pasa?
EDITAR:
Según @High Performance, esto se debe a que Mac sed
tiene 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' *
La -i
opción (alternativamente --in-place
) significa que desea que los archivos se editen en el lugar, en lugar de transmitir el cambio a un nuevo lugar.
La modificación de un archivo in situ sugiere la necesidad de un archivo de copia de seguridad, por lo que se espera una extensión especificada por el usuario después de -i
, pero el análisis del argumento de extensión se maneja de manera diferente en GNU sed y Mac (BSD) sed:
- GNU : "Si no se proporciona ninguna extensión, el archivo original se sobrescribe sin realizar una copia de seguridad". - efectivamente, puedes omitir especificar una extensión de archivo por completo. La extensión debe suministrarse inmediatamente después del
-i
, sin espacio intermedio. - Mac (BSD) : "Si se proporciona una extensión de longitud cero, no se guardará ninguna copia de seguridad". - debe proporcionar una extensión, pero puede ser la cadena vacía '' si lo desea, para deshabilitar la copia de seguridad.
Entonces GNU y Mac interpretarán esto de manera diferente:
sed -i 's/hello/bye/g' jkl.txt
- GNU : no se proporciona ninguna extensión inmediatamente después de
-i
, así que no cree ninguna copia de seguridad, utilícelas/hello/bye/g
como comando de edición de texto y actúe sobre el archivojkl.txt
in situ. - Mac (BSD) : Se utiliza
s/hello/bye/g
la extensión del archivo de copia de seguridad (!), se utilizajkl.txt
como comando de edición de texto, pero ¡oh, oh!: el código de comando proporcionado allí esj
(no, por ejemplos
, un código de comando válido para sustitución), por lo que se produce un error. coninvalid command code j
.
Solución portátil
Para obtener un comando portátil, puede utilizar esta invocación, que funciona tanto en GNU sed
como en Mac (BSD) sed
en Mac OS X Mavericks (v10.9, lanzado en junio de 2013) y versiones posteriores:
sed -i'' -e 's/hello/bye/g' jkl.txt
Colocar la extensión inmediatamente después de -i
(por ejemplo , -i''
o -i'.bak'
, sin un espacio) es lo que sed
espera GNU, y ahora Mac (BSD) también lo acepta sed
, aunque no fue tolerado por versiones anteriores (por ejemplo, con Mac OS X v10.6, un se requería espacio después de -i
, por ejemplo -i '.bak'
).
El -e
parámetro nos permite ser explícitos sobre dónde declaramos el comando de edición.
Hasta que se actualizó Mac OS en 2013, no había ningún comando portátil entre GNU y Mac (BSD), ya que estas variantes también fallaban:
sed -i -e ...
- no funciona en OS X ya que crea-e
copias de seguridadsed -i '' -e ...
- falla en GNU
Cuando no había un sed
comando funcionando en todas las plataformas, podría haber intentado usar otro comando para lograr el mismo resultado, por ejemplo perl -i -pe's/old_link/new_link/g' *
.
Creo que en OS X cuando usas -i se requiere una extensión para los archivos de respaldo . Intentar:
sed -i .bak 's/hello/gbye/g' *
Usando GNU sed
la extensión es opcional .
Esto funciona con las versiones GNU y BSD de sed:
sed -i'' -e 's/old_link/new_link/g' *
o con respaldo:
sed -i'.bak' -e 's/old_link/new_link/g' *
¡ Tenga en cuenta que falta espacio después de -i
la opción! (Necesario para GNU sed)
Tuve el mismo problema en Mac y lo resolvió con brew
:
brew install gnu-sed
y utilizar como
gsed SED_COMMAND
También puede establecer sed
como alias gsed
(si lo desea):
alias sed=gsed