Mi programa Perl toma algo de texto de un archivo de disco como entrada, lo envuelve en algún XML, luego lo envía a STDOUT. La entrada es nominalmente UTF-8, pero a veces se ha insertado basura. Necesito desinfectar la salida de modo que no se emitan octetos UTF-8 inválidos, de lo contrario, el consumidor descendente (Sphinx) explotará.¿Cómo desinfeto el UTF-8 no válido en Perl?
Por lo menos me gustaría saber si los datos son inválidos así que puedo evitar pasarlos; idealmente podría eliminar solo los bytes ofensivos. Sin embargo, habilitar todos los fatalismos que puedo encontrar no me lleva allí con Perl 5.12 (FWIW, use v5.12; use warnings qw(FATAL utf8);
está en vigencia).
Estoy teniendo problemas específicamente con la secuencia "\xFE\xBF\xBE"
. Si creo un archivo que contiene solo estos tres bytes (perl -e 'print "\xEF\xBF\xBE"' > bad.txt
), tratando de leer el archivo con el modo :encoding(UTF-8)
se produce un error con utf8 "\xFFFE" does not map to Unicode
, pero solo debajo de 5.14.0. 5.12.3 y anterior son perfectamente buenas lecturas y más tarde escribir esa secuencia. No estoy seguro de dónde está obteniendo el \xFFFE
(BOM inversa inverso), pero al menos tener una queja es consistente con Sphinx.
Desafortunadamente, decode_utf8("\xEF\xBF\xBE", 1)
no causa errores en 5.12 o 5.14. Preferiría un método de detección que no requiriera una capa de E/S codificada, ya que eso me dejará un mensaje de error y no habrá manera de desinfectar los octetos sin formato.
Estoy seguro de que hay más secuencias que necesito abordar, pero solo manejar esto sería un comienzo. Entonces mis preguntas son: ¿puedo detectar de manera confiable este tipo de datos problemáticos con un perl antes de 5.14? ¿Qué rutina de sustitución generalmente puede desinfectar casi-UTF-8 en estricto UTF-8?
Ejemplos de código: http: // stackoverflow.com/questions/3735721/checklist-for-going-the-unicode-way-with-perl/3736787 # 3736787 – daxim
Gracias, eso es muy útil. Dado que los caracteres Unicode permitidos en XML están bien definidos, 'tr [\ x {9} \ x {A} \ x {D} \ x {20} - \ x {D7FF} \ x {E000} - \ x {FFFD} \ x {10000} - \ x {10FFFF}] [] cd' parece que funcionará, al menos en 5.14. Una sugerencia completamente diferente que encontré no se basa en un nuevo perl en absoluto: 'iconv -c --desde UTF-8 - hasta UTF-8'. –