Necesito reemplazar algunos caracteres no imprimibles con espacios en el archivo.
Específicamente, todos los caracteres de 0x00hasta 0x1F, excepto 0x09(TAB), 0x0A(nueva línea), 0x0D(CR)
Hasta ahora, solo necesitaba reemplazar el 0x00personaje. Como mi sistema operativo anterior era AIX (sin comandos GNU), no puedo usar sed(bueno, puedo pero tenía algunas limitaciones). Entonces, encontré el siguiente comando usando perl, que funcionó como se esperaba:
perl -p -e 's/\x0/ /g' $FILE_IN > $FILE_OUT
Ahora estoy trabajando en Linux, así que esperaba poder usar el sedcomando.
Mis preguntas:
¿Es este comando apropiado para reemplazar esos caracteres? Lo intenté y parece funcionar, pero quiero asegurarme de que:
perl -p -e 's/[\x00-\x08\x0B\x0C\x0E-\x1F]/ /g' $FILE_IN > $FILE_OUTPensé que
perl -pfunciona comosed. Entonces, ¿por qué funciona el comando anterior (al menos, no falla) y el siguiente no?sed -e 's/[\x00-\x08\x0B\x0C\x0E-\x1F]/ /g' $FILE_IN > $FILE_OUTMe dice:
sed: -e expresión # 1, char 34: Carácter de intercalación no válido

perl -pimprime el producto final destdindespués de hacer las operaciones que desea, en este caso es solo reemplazo.sedLa expresión regular podría ser diferente aperl.Respuestas:
Ese es un trabajo típico para
tr:En su caso, no funciona
sedporque está en una ubicación donde esos rangos no tienen sentido. Si desea trabajar con valores de bytes en lugar de caracteres y donde el orden se basa en el valor numérico de esos bytes, lo mejor es utilizar la configuración regional C . Su código habría funcionado conLC_ALL=CGNUsed, pero usarsed(y mucho menosperl) es un poco excesivo aquí (y esos\xXXno son portátiles en lassedimplementaciones, mientras que estetrenfoque es POSIX).También puede confiar en la idea de su localidad de los caracteres imprimibles con:
Pero con GNU
tr(como se encuentra típicamente en los sistemas basados en Linux), eso solo funciona en entornos locales donde los caracteres son de un solo byte (por lo general, no UTF-8).En la configuración regional de C, eso también excluiría DEL (0x7f) y todos los valores de bytes anteriores (no en ASCII).
En las configuraciones regionales UTF-8, puede usar GNU
sedque no tiene el problema que GNUtrtiene:(nota que aquellos
\r,\tno son estándar, y GNUsedno los reconoce siPOSIXLY_CORRECTestá en el medio ambiente (se tratarlos como barra invertida, r y t ser parte del conjunto como requiere POSIX)).Sin embargo, no convertiría bytes que no forman caracteres válidos si los hubiera.
fuente
trhace el comando. Yo entiendo (más o menos) lo queLC_ALL = Ces, pero no todos juntos. Sin embargo,tr -delimina esos caracteres, pero quiero reemplazarlos con espacios. Lo siento, el título estaba mal. Me acabo de dar cuenta, cuando @don_crissti modificó.XCOM. Por ejemplo, los caracteres no ASCII comoÉse codifican (usandood -xa) como0xC9, así que supongo que lo seríaISO-8859-1.locale -apara ver si hay configuraciones regionales con iso8859-1 como el conjunto de caracteres en su sistema y usarLC_CTYPE=<that-locale> tr ...[:print:]...para convertir no imprimibles en esa configuración regional. O puede usar iconv para convertir esos archivos al conjunto de caracteres de su localidad.LC_ALL=en_US.iso88591. Entonces, su comando (tr -c '[:print:]\t\r\n' '[ *]') funciona perfectamente sin modificar la configuración regional o la conversión de archivos. Muchas gracias.Intenté enviar una notificación a través de libnotify, con contenido que puede contener caracteres no imprimibles. Las soluciones existentes no me funcionaron del todo (usando una lista blanca de caracteres usando
trWorks, pero elimina cualquier carácter de varios bytes).Esto es lo que funcionó, mientras pasaba la prueba 💩:
fuente