Me gustaría reemplazar un conjunto de caracteres con los caracteres correspondientes de otro conjunto, algo como esto:
original set: ots
"target" set: u.x
foobartest → fuubar.ex.
Traducciones / transliteraciones como esta son la especialidad del tr
comando:
$ echo 'foobartest' | tr 'ots' 'u.x'
fuubar.ex.
Lamentablemente tr
no admite el cambio de archivos en el lugar como lo sed
hace.
Me gustaría usar sed
para no tener que reinventar la rueda de malabares con los archivos temporales.
tr
(correctamente) ignora la recursividad en los conjuntos de reemplazo:echo 'abc' | tr ab bx
→bxc
. Una solución primitiva podría hacerloxxc
porque vuelve a aplicar la traducción a los caracteres que ya se han traducido.sed
contrario a GNUtr
puede transliterar caracteres de varios bytes)Respuestas:
sed
tiene ely
comando que funciona igual quetr
:El
y
comando es parte de la especificación POSIXsed
, por lo que debería funcionar en casi cualquier plataforma.Y dado que es así
sed
, puede hacer que reemplace un archivo con su versión editada, ahorrándole el molesto negocio de los archivos temporales (siempre que su implementación de seased
compatible con la-i
opción, que no está especificada por POSIX):fuente
sed
la de s no significa que las otras funciones también lo estén. ;) La lista de correo de Vim tiene un hilo sobre encontrar uny/abc/def/
equivalente; La mejor opción parece ser:%call setline(".", tr(getline("."),"abc","def"))
.Si, como en su caso, está transcribiendo caracteres sin cambiar su tamaño (de todos modos, algunas implementaciones como GNU
tr
solo admiten caracteres de un solo byte), puede hacer:Es decir,
tr
sobrescribir el archivo sobre sí mismo.Eso es mejor que
sed -i
en varias cuentas:Un inconveniente es que si se interrumpe, el archivo terminará siendo medio traducido (en este caso, sin embargo, puede ejecutarlo nuevamente para finalizarlo). Algunas
sed
implementaciones manejarían eso correctamente asegurándose de que el archivo original permanezca sin cambios a menos que el comando tenga éxito.fuente
echo 'abc' | tr ab bx
.tr
y en nuestro entorno PXE con muchos enlaces simbólicos,sed -i
era una espera de mierda sucederá ...: /iconv -t cp437
parece más apropiado para eso.iconv
se rompe cuando el archivo de entrada ya contiene bytes codificados con cp437, o una mezcla de codificaciones múltiples. Entonces, aunque es preferible en el caso general, es más robusto hacer reemplazos manuales en este caso.Como otra alternativa, si su problema principal es la falta de soporte para cambiar los archivos en el lugar, es posible que le interese la
sponge
herramienta del paquete moreutils :escribirá en
file
, pero solo se abriráfile
para escribir una vez que se complete la entrada. Desde la página del manual :A menos que tenga archivos realmente grandes que no se pueden guardar en la memoria,
sponge
podría funcionar para usted.fuente
sponge
es que todavía se sobrescribefile
sitr
falla (por ejemplo, si tenía acceso de escritura pero no de lecturafile
)cat file >; file
operador de ksh93 que escribe la salida en un archivo temporal que se renombra al destino solo si el comando tiene éxito (perosed -i
, como , eso crea un nuevo archivo en lugar de sobrescribir el original).