¿Debo usar \ d o para unir los dígitos en una Perl Regex?

Después de leer una serie de preguntas / respuestas en las últimas semanas, he visto el uso de las expresiones regulares \d en perl comentadas como incorrectas. Como en las versiones posteriores de perl \d no es lo mismo que [0-9] , ya que \d representará cualquier carácter Unicode que tenga el atributo de dígito, y que [0-9] represente los caracteres ‘0’, ‘1 ‘,’ 2 ‘, …,’ 9 ‘.

Aprecio que en algunos contextos [0-9] será lo correcto para usar, y en otros \d lo será. Me preguntaba qué personas creen que es el valor predeterminado correcto para usar.

Personalmente encuentro que la notación \d muy breve y expresiva, mientras que en comparación [0-9] es algo engorroso. Pero tengo poca experiencia en hacer código en varios idiomas, o más bien código para idiomas que no encajan en el rango de caracteres ASCII, y por lo tanto, puede estar siendo ingenuo.

me doy cuenta

 $find /System/Library/Perl/5.8.8/ -name \*pm | xargs grep '\\d' | wc -l 298 $find /System/Library/Perl/5.8.8/ -name \*pm | xargs grep '\[0-9\]' | wc -l 26 

Para una seguridad máxima, sugiero usar [0-9] cada vez que no intente específicamente hacer coincidir todos los dígitos definidos en Unicode.

Por perldoc perluniintro , Perl no admite el uso de dígitos distintos de [0-9] como números, por lo que definitivamente usaría [0-9] si los siguientes son verdaderos:

  1. Desea utilizar el resultado como un número (como realizar operaciones matemáticas en él o almacenarlo en algún lugar que solo acepte números adecuados (por ejemplo, una columna INT en una base de datos)).

  2. Es posible que no-dígitos [^0-9] estén presentes en los datos de tal manera que la expresión regular podría coincidir con ellos. (Tenga en cuenta que este siempre debe considerarse verdadero para la entrada no confiable / hostil).

Si cualquiera de estos es falso, rara vez habrá motivo para no usar específicamente \d (y probablemente podrá saber cuándo es el caso), y si está intentando hacer coincidir todos los dígitos definidos para unicode, definitivamente querrás usar \d .

Me parece muy peligroso usar \d , es una decisión de diseño deficiente en el lenguaje, como en la mayoría de los casos desea [0-9] . La encoding de Huffman dictaría el uso de \d para los números ASCII.

La mayoría de los carteles anteriores ya han resaltado por qué debes usar [0-9] , así que déjame darte un poco más de información:

  • Si leo correctamente los gráficos Unicode, ‘ ۷۰ ‘ es un número (70 en indic, no lo creo).

  • Prueba esto:

     $ perl -le '$one = chr 0xFF11; print "$one + 1 = ", $one+1;' 1 + 1 = 1 
  • Aquí hay una lista parcial de números válidos (que pueden aparecer o no correctamente en su navegador, dependiendo de las fonts que use), para cada número, solo el primero de ellos se interpreta como un número cuando se hace aritmética con Perl, como mostrado anteriormente:

      ZERO: 0٠۰߀०০੦૦୦௦౦೦൦๐໐0 ONE: 1١۱߁१১੧૧୧௧౧೧൧๑໑1 TWO: 2٢۲߂२২੨૨୨௨౨೨൨๒໒2 THREE: 3٣۳߃३৩੩૩୩௩౩೩൩๓໓3 FOUR: 4٤۴߄४৪੪૪୪௪౪೪൪๔໔4 FIVE: 5٥۵߅५৫੫૫୫௫౫೫൫๕໕5 SIX: 6٦۶߆६৬੬૬୬௬౬೬൬๖໖6 SEVEN: 7٧۷߇७৭੭૭୭௭౭೭൭๗໗7 EIGHT: 8٨۸߈८৮੮૮୮௮౮೮൮๘໘8 NINE: 9٩۹߉९৯੯૯୯௯౯೯൯๙໙9   

¿Todavía no estás convencido?

De acuerdo con perlreref , ‘ \d ‘ es consciente de la configuración regional y consciente de Unicode.

Sin embargo, si el conjunto de códigos que está utilizando no es Unicode, entonces no necesita preocuparse por los dígitos Unicode, y si el conjunto de códigos que está utilizando es algo así como Latin-1 (ISO 8859-1, o 8859-15), entonces la conciencia local tampoco te hará daño porque el conjunto de códigos no incluye ningún otro dígito.

Entonces, para muchas personas, la mayoría de las veces, puedes usar ‘ \d ‘ sin preocuparte. Sin embargo, si los datos de Unicode son parte de tu trabajo, entonces debes considerar lo que buscas con más cuidado.

Al igual que aniquilar el sitio desde la órbita, [0-9] es la única forma de estar seguro. Sí, es feo. Sí, la elección de hacer que \d sea ​​UNICODE y consciente de la configuración regional era estúpido. Pero esta es nuestra cama y tenemos que mentir en ella.

En cuanto a las personas que agachan la cabeza en la arena diciendo que no afecta el juego de caracteres que están usando hoy, bien puede que estés usando ese juego de personajes hoy, pero el rest del mundo está usando UTF-8 ahora y estarás usándolo pronto también. Recuerde codificar como si el tipo que mantiene su código es un maníaco homicida que sabe dónde vive.

Ah, y en cuanto a los módulos Perl que usan \d vs [0-9] , incluso el núcleo todavía tiene problemas UNICODE .

Si de hecho significa cualquier dígito, pero desea poder hacer cálculos matemáticos con los resultados, puede usar Text::Unidecode :

 #!/usr/bin/perl use strict; use warnings; use Text::Unidecode; my $number = "\x{1811}\x{1812}\x{1813}\x{1814}\x{1815}"; print "$number is ", unidecode($number), "\n"; 

Después de algunas pruebas más, parece que Text :: Unidecode no maneja todos los caracteres de dígitos correctamente. Estoy escribiendo un módulo que funcionará.

Siento que ambos deben tener su lugar. Sin embargo, el 99,999% de las veces (especialmente en mi gran mundo cerrado de cooperación estadounidense) son intercambiables. Uso perl para manipular datos todos los días y en ninguno de los conjuntos de datos con los que trato hay números que no encajan en [0-9] . Sin embargo, aprecio que haya una distinción importante entre \d y [0-9] y es bueno estar al tanto de esa diferencia. Uso \d porque parece más sucinto (como dijiste) y nunca estaría “mal” en mi pequeño mundo de manipulación de datos.

Si aplica \d a una cadena Unicode (como en "\X{660}" =~ /\d/ ), coincidirá con un dígito Unicode. Si aplica \d a una cadena binaria (como el equivalente UTF-8 de arriba: "\xd9\xa0" =~ /\d/ ), solo coincidirá con los 10 dígitos ASCII. Perl 5.8 no crea cadenas Unicode por defecto (a menos que lo solicite específicamente, como en "\X{...}" o use utf8; etc.).

Entonces mi consejo es: solo presta atención a la diferencia entre \d y [0-9] si tu aplicación usa cadenas Unicode.

Si [0-9] siente torpe, quizás pueda definir: $d=qr/[0-9]/; y use eso en lugar de \d .

A medida que aumentan los controles de formato de datos, la necesidad de especificidad de patrón disminuye …

Por ejemplo, si está haciendo coincidir una pieza de datos que se ha generado en la máquina y siempre sigue las mismas reglas de formato de salida, no necesita ser tan preciso. Toma direcciones IPv4. Si está intentando extraer la dirección IP de la línea de configuración de la interfaz del enrutador, todo lo que realmente necesita es algo como:

  'ip\haddress\h(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\D' 

Si, por otro lado, está tratando de encontrar una dirección IP incrustada en algún lugar, por ejemplo, en un encabezado X del correo electrónico, o si está tratando de VALIRAR una dirección IP, bueno … ¡eso es toda una historia!