web-dev-qa-db-fra.com

Devrais-je utiliser\d ou [0-9] pour faire correspondre les chiffres dans une expression rationnelle Perl?

Après avoir lu un certain nombre de questions/réponses au cours des dernières semaines, j'ai constaté que l'utilisation de \d dans les expressions rationnelles Perl était commentée comme étant incorrecte. Comme dans les versions ultérieures de Perl, \d n'est pas identique à [0-9], car \d représentera tout caractère Unicode ayant l'attribut digit et que [0-9] représente les caractères '0', '1', '2', ..., '9'.

J'apprécie que dans certains contextes, [0-9] sera la bonne chose à utiliser, et dans d'autres, \d sera. Je me demandais quelles personnes pensent être le bon choix à utiliser?

Personnellement, je trouve la notation \d très succincte et expressive, alors que, par comparaison, [0-9] est quelque peu encombrante. Mais j’ai peu d’expérience dans la création de code multilingue, ou plutôt de code pour les langues ne correspondant pas à la plage de caractères ASCII, et peut donc être naïf.

Je remarque

$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
45
Beano

Pour une sécurité maximale, nous vous suggérons d'utiliser [0-9] chaque fois que vous n'avez pas l'intention de faire correspondre tous les chiffres définis par Unicode.

Per perloc perluniintro , Perl ne prend pas en charge l’utilisation de chiffres autres que [0-9] en tant que nombres. J’utiliserai donc certainement [0-9] si les éléments suivants sont vrais:

  1. Vous souhaitez utiliser le résultat sous forme de nombre (par exemple en effectuant des opérations mathématiques ou en le stockant dans un endroit qui accepte uniquement les nombres appropriés (par exemple une colonne INT dans une base de données)).

  2. Il est possible que [^0-9] non digits soit présent dans les données de telle sorte que l'expression régulière puisse leur correspondre. (Notez que celui-ci devrait toujours être considéré comme vrai pour les entrées non fiables/hostiles.)

Si l'un de ces éléments est faux, il n'y aura que rarement des raisons d'utiliser spécifiquement pas utiliser \d (et vous serez probablement en mesure de dire quand c'est le cas), et si vous essayez de correspond à tous les chiffres définis par Unicode, vous voudrez certainement utiliser \d.

38
Nicholas Knight

Il me semble très dangereux d’utiliser \d. C’est une mauvaise décision de conception dans la langue, car dans la plupart des cas, vous souhaitez [0-9]. Le codage de Huffman dicterait l’utilisation de \d pour les nombres ASCII. 

La plupart des affiches précédentes ont déjà expliqué pourquoi vous devriez utiliser [0-9], alors laissez-moi vous donner un peu plus de données: 

  • Si je lis correctement les graphiques unicode, '۷۰' est un nombre (70 en indic, ne prenez pas ma parole pour cela).

  • Essaye ça: 

    $ Perl -le '$one = chr 0xFF11; print "$one + 1 = ", $one+1;'
    1 + 1 = 1
    
  • Voici une liste partielle des nombres valides (qui peuvent ou non apparaître correctement dans votre navigateur, en fonction des polices que vous utilisez), pour chaque numéro, seul le premier de ceux-ci étant interprétés comme un nombre lorsqu’une opération arithmétique avec Perl, comme montré ci-dessus:

     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��
    

Es-tu toujours pas convaincu?

52
mirod

Selon perlreref , '\d' est sensible à la localisation et à Unicode.

Toutefois, si le jeu de codes que vous utilisez n'est pas Unicode, vous n'avez pas à vous soucier des chiffres Unicode, et si le jeu de codes que vous utilisez est similaire à Latin-1 (ISO 8859-1 ou 8859-15), alors, la connaissance des paramètres régionaux ne vous fera pas de mal non plus, car le jeu de codes ne comprend aucun autre caractère numérique.

Donc, pour la plupart des gens, vous pouvez utiliser '\d' sans souci. Toutefois, si les données Unicode font partie de votre travail, vous devez examiner de plus près ce que vous recherchez.

8
Jonathan Leffler

Tout comme pour quitter le site d’orbite, [0-9] est le seul moyen d’en être sûr. Oui, c'est moche. Ouais, le choix de faire \d être UNICODE et de tenir compte des paramètres régionaux était stupide. Mais ceci est notre lit et nous devons nous y coucher.

Si les gens se cachent la tête dans le sable en disant que cela n’affecte pas le jeu de caractères qu’ils utilisent aujourd’hui, eh bien, vous utilisez peut-être ce jeu de caractères aujourd’hui, mais le reste du monde utilise maintenant UTF-8 et vous le ferez. l'utiliser bientôt aussi. N'oubliez pas de coder, comme le gars qui maintient votre code est un maniaque meurtrier qui sait où vous habitez.

Oh, et comme pour les modules Perl utilisant \d vs [0-9], même le noyau a toujours Problèmes UNICODE .

Si vous voulez parler de n'importe quel chiffre, mais que vous voulez être capable de faire des calculs avec les résultats, vous pouvez utiliser 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";

Après quelques tests supplémentaires, il semble que Text :: Unidecode ne gère pas correctement tous les caractères numériques. J'écris un module qui fonctionnera.

5
Chas. Owens

Je sens que les deux doivent avoir leur place. Cependant, ils sont interchangeables dans 99,999% des cas (surtout dans le monde de la grande coopération américaine). J'utilise Perl pour manipuler les données tous les jours et aucun des ensembles de données que je traite ne contient de chiffres qui ne rentrent pas dans [0-9]. Cependant, j’apprécie qu’il existe une distinction importante entre \d et[0-9] et il est bon de prendre conscience de cette différence. J'utilise \d car il semble plus succinct (comme vous l'avez dit) et ne serait jamais «faux» dans mon petit monde de manipulation de données.

3
Copas

Si vous appliquez \d à une chaîne Unicode (telle que dans "\X{660}" =~ /\d/), elle correspondra à un chiffre Unicode. Si vous appliquez \d à une chaîne binaire (telle que l'équivalent UTF-8 de ce qui précède: "\xd9\xa0" =~ /\d/), elle ne correspond qu'aux 10 chiffres ASCII. Perl 5.8 ne crée pas de chaînes Unicode par défaut (à moins que vous ne le demandiez spécifiquement, comme dans "\X{...}" ou use utf8;, etc.).

Mon conseil est donc: ne faites attention qu'à la différence entre \d et [0-9] si votre application utilise des chaînes Unicode.

2
pts

Si [0-9] semble maladroit, vous pourriez peut-être définir: $d=qr/[0-9]/; et l'utiliser à la place de \d.

1
Mattias

À mesure que les contrôles de format de données augmentent, le besoin de spécificité de modèle diminue ...

Par exemple, si vous correspondez à une donnée générée par une machine et qui suit toujours les mêmes règles de formatage de sortie, vous n'avez pas besoin d'être aussi précis .. Prenez les adresses IPv4. Si vous essayez d'extraire l'adresse IP d'une ligne de configuration d'interface de routeur, il vous suffit de:

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

SI, d’autre part, vous essayez de trouver une adresse IP profondément intégrée quelque part dans un en-tête de courrier électronique, par exemple, ou si vous essayez de valider une adresse IP, eh bien… c’est tout une histoire!

0
skeetastax