Tengo un requisito en mi proyecto para reemplazar parte del texto existente en un archivo como foo
con algún otro texto como fooofoo
:
abc.txt
name
foo
foo1
Entonces intenté:
sed -i "s/foo/fooofoo/g" abc.txt
Sin embargo me sale este error:
sed: opción ilegal
i
Encontré en el manual que tengo que usar:
sed -i\ "s/foo/fooofoo/g" abc.txt
Sin embargo, esto tampoco funciona.
Encontré alternativas perl
y awk
también, pero una solución en Solaris sed
sería muy apreciada.
Estoy usando esta versión de bash:
GNU bash, versión 3.2.57 (1) -release (sparc-sun-solaris2.10)
text-processing
sed
solaris
tpsaitwal
fuente
fuente
/usr/gnu/bin/sed
para obtener soporte -i.Respuestas:
Uso
ed
. Está disponible en la mayoría de las plataformas y puede editar sus archivos en el lugar.Dado que
sed
se basa ened
la sintaxis para reemplazar patrones es similar:fuente
ed
lugar deex
solo curiosidad? (Sé que ambos son compatibles con POSIX y me he vinculado a las especificaciones.))ex
? Para responder a su pregunta: como nunca usoex
no estoy familiarizado con él. por cierto, he visto configuraciones dondeed
estaba presente peroex
no estaba (pero no al contrario) ... el más notable es mi computadora portátil :)ex
comandos. Todos losvi
comandos que puede escribir que comienzan con dos puntos sonex
comandos. Por supuesto, hay algunas extensiones específicas de Vim, pero solo el conjunto central de comandos es increíblemente potente y flexible y es suficiente para las ediciones con script.ex
y aún noed
.Si no puede instalar GNU sed, use:
Esto utiliza la redirección para enviar la salida de sed a un archivo temporal. Si sed se completa con éxito, esto se sobrescribe
abc.txt
con el archivo temporal.Como se puede ver en el código fuente de GNU sed , esto es exactamente lo que
sed -i
hace. Entonces, esto es casi tan eficiente comosed -i
.Si ya existe una posibilidad
abc.tmp
, es posible que desee utilizarmktemp
una utilidad similar o similar para generar el nombre único para el temporal.fuente
ed
, ya que lee todo el archivo en la memoria.Si quieres el equivalente de
sed -i.bak
, es bastante simple.Considere este script para GNU sed:
Simplemente podemos reemplazar la línea marcada con
Esto mueve el archivo existente para que sea una copia de seguridad y escribe un nuevo archivo.
Si queremos el equivalente de
entonces es un poco más complejo. Podemos abrir el archivo para leerlo como entrada estándar, luego desvincularlo, antes de dirigir la salida de sed para reemplazarlo:
Hacemos esto en un sub-shell, para que nuestro stdin original todavía esté disponible después de esto. Es posible cambiar las entradas y volver sin un subshell, pero de esta manera me parece más claro.
Tenga en cuenta que tenemos cuidado de copiar primero, en lugar de crear un nuevo
foo
archivo; esto es importante si el archivo se conoce por más de un nombre (es decir, tiene enlaces duros) y desea asegurarse de no romper los enlaces .fuente
Primero, debe saber que el
i\
comando al que se refiere es para insertar una línea de texto, no para guardar el texto editado nuevamente en el archivo. No hay una forma de POSIX especificada para usarsed
para eso.Lo que puede hacer es usar
ex
, que está especificado por POSIX :El
x
comando es para "guardar y salir". También puedes usarlowq
perox
es más corto.El
%
signo al comienzo del comando sustituto significa "Aplicar este comando a cada línea en el búfer". Podrías usar1,$s/find/replace/g
también.Una diferencia importante entre
ex
ysed
es quesed
es un editor de flujo . Solo funciona secuencialmente, línea por línea.ex
es mucho más flexible que eso, y de hecho puedes editar archivos de texto interactivos directamente enex
. Es el predecesor inmediato devi
.fuente
Usando
sed
y sin archivo temporal visible :Puede evitar crear un "archivo temporal" visible separado :
Explicación
Los sistemas tipo Unix en realidad no eliminan el contenido del archivo del disco hasta que ambos estén desvinculados en el sistema de archivos y no se abran en ningún proceso. Entonces puede hacer
exec 3<
para abrir el archivo en el shell para leer en el descriptor de archivo 3,rm
el archivo (que lo desvincula del sistema de archivos), y luego llamarsed
con el descriptor de archivo 3 utilizado como entrada.Tenga en cuenta que esto es muy diferente de esto:
La diferencia es que cuando lo hace en un comando, el shell simplemente abre el mismo archivo tanto para leer como para escribir con la opción de truncar el archivo, ya que sigue siendo el mismo archivo, pierde el contenido. Pero si lo abre para leerlo, luego
rm
abre el mismo nombre de ruta para escribir, en realidad está creando un nuevo archivo con el mismo nombre de ruta (pero en un nuevo inodo y ubicación de disco, ya que el original todavía está abierto): entonces los contenidos aún están disponibles.Luego, una vez que haya terminado, puede cerrar el descriptor de archivo que abrió anteriormente (eso es lo que hace la
exec 3<&-
sintaxis especial), que libera el archivo original para que el sistema operativo pueda eliminar (marcar como no utilizado) su espacio en disco.Advertencias
Hay algunas cosas a tener en cuenta sobre esta solución:
Solo obtiene una "lectura" a través del contenido: no hay una forma portátil de que un shell "busque" de nuevo en el descriptor de archivo, por lo que una vez que un programa lee algunos de los contenidos, otros programas solo verán el resto del archivo. Y
sed
leerá todo el archivo.Hay una pequeña posibilidad de que su archivo original se pierda si su shell / script / sed se mata antes de que se haga.
fuente
perl -i
es otra buena opción. La pregunta solicitó específicamente una solución compatible con Solaris 'sed
, en contraste con las soluciones conperl
yawk
que mencionaron que ya se encuentran. Además, mi respuesta tenía como objetivo principal agregar algo que pensé que era útil saber y que faltaba en cualquiera de las otras respuestas.