sustituir regulares parametros minusculas mayusculas linea expresiones especiales eliminar ejemplos caracteres caracter añadir regex bash utf-8 sed chinese-locale

regex - regulares - Usando sed, ¿cómo puede una expresión regular emparejar caracteres chinos?



sed shell (2)

Decidí publicar una pregunta, después de pasar bastante tiempo y aún no resolver el problema. También leí un montón de publicaciones aparentemente relacionadas, ninguna realmente se ajustaba a mi problema simple (?).

Así que tengo un archivo de texto posiblemente grande (> 1000 líneas) que contiene caracteres chinos mandarín, con una línea de muestra como:

"ref#2-5-1.jpg#2#一些 <variable> 内容#pic##" (the Chinese just means "some content").

Todo lo que necesita modificarse es que se debe insertar un espacio entre cada personaje, si no hay uno ya:

"ref#2-5-1.jpg#2#一 些 <variable> 内 容#pic##".

Empecé ingenuamente con cosas sencillas como las siguientes, pero no hay ninguna coincidencia:

sed -e ''s//([/u4E00-/u9fff]/)//1 /g'' <test_utf_sed.txt > test_out.txt

donde se supone que 4E00-9fff es el rango de código para el chino mandarín. Sorprendentemente, esto no funcionó, así que también quise probar

sed -e ''s//([一-龻]/)/hello/g'' <test_utf_sed.txt > test_out.txt

Esto falló porque mi bash no puede mostrar (?) El carácter "一".

Luego hice una prueba básica, que también falló:

sed -e ''s//(/u4E00/)/hello/g'' <test_utf_sed.txt > test_out.txt //一 sed -e ''s//(/u4E9B/)/hello/g'' <test_utf_sed.txt > test_out.txt //些

Lo mismo con otra notación para codificación utf (que se encuentra aquí en stackoverflow):

sed -e ''s//(/u''U+4E00/)/hello/g'' <test_utf_sed.txt > test_out.txt

1) Como una herramienta para tratar con caracteres de doble byte, ¿es la elección correcta?

2) ¿Es capaz de manejar unicode en absoluto, o necesito un interruptor especial?

3) No estoy buscando una solución alternativa como esta:

step1: insert space after each character //like ''s//(./)//1 /g'') step2: remove space after each chacter which is not a Chinese character //like ''s//([a-zA-Z0-9]/) //1/g'')

Sé cómo hacer esto, pero es poco elegante y propenso a errores. Esto debe ser posible usando utf-8 en regex in sed.

4) Mi entorno es bash-3.2 en un MacOS 10.6.8 (sistema operativo antiguo).

5) Si conoces algunos indicadores para algunos regEx-onliners abiertos como biblioteca que trata sobre el procesamiento de texto o lenguaje chino, sería genial compartirlos.

Muchas gracias de antemano, su ayuda es muy apreciada!


Perl tiene un soporte bastante bueno para tratar con Unicode. Esa podría ser una mejor apuesta para tu tarea que sed. Este one-liner funciona como tu primer ejemplo sed:

perl -CIOED -p -e ''s//p{Block=CJK_Unified_Ideographs}/$& /g'' filename

El -CIOED le dice a Perl que haga su E / S en utf8. -p ejecuta el código dado una vez para cada línea del archivo de entrada, luego imprime el resultado. -e especifica una línea de código Perl para ejecutar. Consulte la documentación en los argumentos de línea de comandos para más.

La expresión regular utiliza rangos con nombre para identificar los caracteres que coinciden.

Es posible que también desee leer la documentación de Perl Unicode .


sed no comprende /u secuencias de escape (aparentemente). No sé si bash-3.2 tampoco, pero creo que sí; si es así, podrías escribir

sed $''s//u4E9B/hello/g''

pero aún no sería capaz de hacer la especificación de rango.

Sin embargo, al traducir a UTF-8 a mano, podría llegar a la siguiente expresión regular extendida que, en mi opinión, coincidirá con cualquier secuencia UTF-8 para un personaje en el rango U + 4E00 ... U + 9FFF:

(/xe4[/xb8-/xbf][/x80-/xbf]|[/xe5-/xe9][/x80-/xbf][/x80-/xbf])

(Pero los rangos de caracteres solo funcionarán si invoca sed en una configuración regional de un solo byte, preferiblemente la configuración regional C )

Con GNU sed , obtienes expresiones regulares extendidas si proporcionas el -r . Con MacOSX creo que necesitas la bandera -E . Entonces podrías probar:

LANG=C sed -E / $''s/(/xe4[/xb8-/xbf][/x80-/xbf]|[/xe5-/xe9][/x80-/xbf][/x80-/xbf])///1 /g'' / <test_utf_sed.txt >test_out.txt

(Lo anterior le permite a bash manejar los /x escapes. Si omites los $ , entonces sed manejará los /x escapes, pero tendrás que cambiar la sustitución de //1 a /1 No tengo un Mac, ni tienen la versión anterior de bash, así que realmente no sé si tu sed escapa hex o no, estoy bastante seguro de que tu bash lo hará, pero no puedo garantizarlo).

Por cierto, no es tan difícil obtener las codificaciones de utf-8 para esos personajes; Lo hice con un pequeño copiar y pegar de la publicación original. P.ej.:

$ hd <<<"一些" 00000000 e4 b8 80 e4 ba 9b 0a |.......|

Es útil saber que todo el rango de ideogramas del plano 0 (U + 4E00 ... U + 9FFF) tiene códigos de tres bytes, por lo que 一 es E4 B8 80 y 些 es E4 BA 9B . (El 0A es, por supuesto, un final de línea).