2008-10-15 8 views
8

Estoy buscando una manera de hacer coincidir solo caracteres completamente compilados en una cadena Unicode.¿Cómo comparo solo caracteres completamente compilados en una cadena Unicode en Perl?

¿[:print:] depende de la configuración regional en cualquier implementación de expresiones regulares que incorpore esta clase de caracteres? Por ejemplo, ¿coincidirá con el carácter japonés 'あ', ya que no es un carácter de control, o es [:print:] que siempre va a ser códigos ASCII 0x20 a 0x7E?

¿Hay alguna clase de caracteres, incluidos Perl RE, que se pueda usar para hacer coincidir algo que no sea un carácter de control? Si [:print:] incluye solo caracteres en el rango ASCII, asumiría que [:cntrl:] también lo hace.

Respuesta

6
echo あ| perl -nle 'BEGIN{binmode STDIN,":utf8"} print"[$_]"; print /[[:print:]]/ ? "YES" : "NO"' 

Esto funciona principalmente, aunque genera una advertencia sobre un carácter ancho. Pero te da la idea: debes estar seguro de que estás tratando con una cadena Unicode real (comprueba utf8 :: is_utf8). O simplemente marque perlunicode, todo el tema todavía me da vueltas.

+1

Puede deshacerse del feo BEGIN {binmode STDIN, ": utf8"} kludge al proporcionar la opción -CS en la línea de comando. – moritz

+0

... que también hará que la advertencia desaparezca, porque configura STDOUT de la misma manera que STDIN. – moritz

+0

Puede no ser una gran opción si el OP escribe un módulo para manejar esto en lugar de un script independiente. Así que voy a dejar mi solución, así como su solución con la esperanza de que el OP pueda descubrir cuál es mejor para su situación. Gracias :-) – Tanktalus

2

Sí, esas expresiones dependen de la configuración regional.

+0

¿Puede nombrar un entorno y/o una implementación de expresión regular que permita que [: print:] respete una configuración/codificación UTF-8 japonesa? Estoy usando Perl en Linux con configuración/codificación UTF-8 japonesa y no coincide con el carácter japonés. – dreamlax

1

Puede usar siempre la clase de caracteres [^[:cntrl:]] para que coincida con los caracteres que no son de control.

+1

Esto no coincide con los caracteres de control Unicode (en la configuración de mi entorno y con Perl). Hay caracteres de control Unicode para cambiar la dirección del texto, etc. Usar [^ [: ctrnl:]] coincidirá con estos Unicode pero no con ASCII. – dreamlax

5

Creo que no quieres o no necesitas configuraciones regionales para eso, sino Unicode. Si ha descodificado una cadena de texto, \w coincidirá con los caracteres de las palabras en cualquier idioma, \d coincide no solo con 0..9 sino con cada dígito Unicode, etc. En expresiones regulares, puede consultar las propiedades Unicode con \p{PropertyName}. Particularmente interesante para usted podría ser \p{Print}. Here's a list of all the available Unicode character properties.

Escribí un article about the basics and subtleties of Unicode and Perl, debería darle una buena idea sobre qué hacer que perl reconocerá su cadena como una secuencia de caracteres, no solo una secuencia de bytes.

Actualización: con Unicode no se obtiene un comportamiento que dependa del idioma, sino que se utiliza el mismo estado de forma predeterminada, independientemente del idioma. Esto puede o no ser lo que quieres, pero para la distinción de carácter priintable/control no veo por qué necesitarías un comportamiento que dependa del idioma.

4

\X coincide con un carácter completamente compuesto (secuencia). Prueba:

#!/usr/bin/env perl 
use 5.010; 
use utf8; 
use Encode qw(encode_utf8); 

for my $string (qw(あ ご ご), "\x{3099}") { 
    say encode_utf8 sprintf "%s $string", $string =~ /\A \X \z/msx ? 'ok' : 'nok'; 
} 

Los datos de prueba son los siguientes: un carácter normal, un carácter pre-combinada, una secuencia de combinación de caracteres y una combinación de caracteres (que "no cuenta" por sí solo, una simplificación del capítulo 3 de Unicode).

Sustituya \X con para ver que la respuesta de Tanktalus produce coincidencias falsas para los dos últimos casos.

Cuestiones relacionadas