¿Cómo evitar que Sed cambie el formato del archivo?

¿Cómo evitar que Sed cambie el formato del archivo?

Estaba intentando usar un archivo sed para preprocesar un archivo, pero la salida de sed parece cambiar el formato. ¿Cómo debo evitarlo?

file A.txt
A.txt UTF-8 Unicode English text, with very long lines

sed -f process.sed < A.txt > B.txt

head -2 process.sed
#!/bin/sed -f
s/[‘’"“”•·・、。《》™®\.★☆]\\[a-z\-]\+ //g

file B.txt
Non-ISO extended-ASCII English text, with very long lines, with LF, NEL line terminators

Debido a que B.txt no está codificado en UTF-8, no puedo realizar el siguiente procesamiento.

vim B.txt
è·¯æ<98><93>æ<96>¯ Âç½<97>å¾·é<87><8c>æ ¼æ<96>¯ //è·¯æ<98><93>æ<96>¯Â·ç½<97>å¾·é<87><8c>æ ¼æ<96>¯ ]

Respuesta1

El problema es que el motor de expresiones regulares de sed no ve su archivo de entrada ni su […]coincidencia como una lista de caracteres Unicode; en cambio, ve cada uno de ellos como múltiples bytes independientes. Por ejemplo, ve tres bytes \xe2 \x80 \xa2e intenta comparar cada uno de ellos individualmente [ \xe2 \x80 \x98 \xe2 \x80 \x99 \x22 \xe2 \x80 ... ].

Entonces, en el ejemplo que mostró en su publicación, la expresión regular solo coincide y elimina el último byte de cada carácter de puntuación, pero deja los otros 2 todavía allí. Eso es lo que le da un archivo de salida no válido (no UTF-8).

Con GNU sed (probado en 4.5), esto se puede evitar asegurándose de que elconfiguración regional del sistema(las variables de entorno $LANG o al menos $LC_CTYPE) están configuradas en una configuración regional compatible con UTF-8. Por ejemplo:

$ exportar LANG='C'
$ echo ''prueba' “prueba”' | sed 's/[“”•]/X/g'
XX�pruebaXX� XXXpruebaXXX
$ eco '•_prueba' | sed 's/[•‡]_/X_/'
��X_prueba

$ exportar LANG='en_US.UTF-8'
$ echo ''prueba' “prueba”' | sed 's/[“”•]/X/g'
'prueba' XtestX
$ eco '•_prueba' | sed 's/[•‡]_/X_/'
X_prueba

(El idioma local no importa.CualquierLa configuración regional UTF-8 funcionará).

Si esto no funciona para usted, evítelo […]por completo y use \(…\|…\|…\)(o (…|…|…)en sed -r), que es una alternativa de varios caracteres y funcionará independientemente de cómo se terminen interpretando esos caracteres.

$ exportar LANG='C'
$ echo ''prueba' “prueba”' | sed 's/\(“\|”\|•\)/X/g'
'prueba' XtestX
$ eco '•_prueba' | sed 's/\(•\|‡\)_/X_/'
X_prueba

información relacionada