2009-05-20 8 views
36

Dopo aver letto un numero di domande/risposte nelle ultime settimane, ho visto l'uso di \d in espressioni regolari perl commentate come non corrette. Come nelle versioni successive di perl \d non corrisponde a [0-9], come \d rappresenterà qualsiasi carattere Unicode con l'attributo digit e che [0-9] rappresenta i caratteri "0", "1", "2", ..., '9'.Devo usare d o [0-9] per abbinare le cifre in un'espressione regolare Perl?

Apprezzo che in alcuni contesti [0-9] sarà la cosa corretta da utilizzare e in altri \d sarà. Mi stavo chiedendo quali persone ritengono sia l'impostazione predefinita corretta da utilizzare?

Personalmente trovo la notazione \d molto succinta ed espressiva, mentre nel confronto [0-9] è piuttosto ingombrante. Ma ho poca esperienza di fare codice multi-lingua, o piuttosto codice per linguaggi che non rientrano nell'intervallo di caratteri ASCII, e quindi può essere ingenuo.

ho notato

$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 

risposta

28

Per la massima sicurezza, suggerirei di utilizzare [0-9] ogni volta che non si intende specificamente abbinare tutte le cifre definite in modo unicode.

Per perldoc perluniintro, Perl non supporta l'utilizzo cifre diverse da [0-9] come numeri, così avrei sicuramente utilizzare [0-9] se i seguenti sono entrambe vere:

  1. si desidera utilizzare il risultato come un numero (come eseguire operazioni matematiche su di esso o memorizzarlo da qualche parte che accetta solo numeri corretti (es. una colonna INT in un database)).

  2. È possibile che i dati non presenti [^0-9] siano presenti in modo tale che l'espressione regolare possa corrisponderli. (Si noti che questo dovrebbe sempre essere considerato vero per l'input non attendibile/ostile.)

Se uno di questi sono false, non ci sarà solo raramente essere motivo di particolare non uso \d (e si' Probabilmente sarà in grado di capire quando questo è il caso), e se sei cercando di corrispondere a tutte le cifre definite in modo unicode, ti consigliamo di utilizzare lo \d.

+2

\ d può infatti corrispondere a più di 10 caratteri diversi, se applicato alle stringhe Unicode. – pts

3

mi sento entrambi devono avere il loro posto. Tuttavia, il 99,999% delle volte (specialmente nel mio grande mondo di cooperazione americano chiuso) sono intercambiabili. Uso perl per manipolare i dati ogni giorno e in nessuno dei set di dati con cui ho a che fare ci sono numeri che non rientrano in [0-9]. Tuttavia, apprezzo che ci sia un'importante distinzione tra \d e [0-9] ed è bene essere consapevoli di questa differenza. Io uso \d perché sembra più succinto (come hai detto tu) e non sarebbe mai "sbagliato" nel mio piccolo mondo di manipolazione dei dati.

+0

Si desidera \ d non/d - se lo si desidera affatto. – Telemachus

2

Se si applica \d a una stringa Unicode (ad esempio in "\X{660}" =~ /\d/), corrisponderà a una cifra Unicode. Se si applica \d a una stringa binaria (come l'equivalente UTF-8 di quanto sopra: "\xd9\xa0" =~ /\d/), corrisponderà solo alle 10 cifre ASCII. Perl 5.8 non crea stringhe Unicode per impostazione predefinita (a meno che non lo richieda espressamente, ad esempio in "\X{...}" o use utf8; ecc.).

Quindi il mio consiglio è: prestare attenzione alla differenza tra \d e [0-9] se l'applicazione utilizza stringhe Unicode.

8

In base a perlreref, '\d' è consapevole delle impostazioni internazionali e Unicode.

Tuttavia, se il set di codici che si utilizza non è Unicode, non è necessario preoccuparsi delle cifre Unicode e se il set di codici utilizzato è simile a Latin-1 (ISO 8859-1 o 8859 -15), quindi la consapevolezza della localizzazione non ti farà male perché il codeset non include nessun altro carattere numerico.

Quindi, per molte persone, il più delle volte, è possibile utilizzare "\d" senza problemi. Tuttavia, se i dati Unicode fanno parte del tuo lavoro, devi considerare attentamente ciò che stai cercando.

4

Proprio come il nuotare il sito dall'orbita, [0-9] è l'unico modo per essere sicuri. Sì, è brutto. Sì, la scelta di rendere \d UNICODE e le impostazioni locali erano stupide. Ma questo è il nostro letto e dobbiamo mentirci.

Per quanto riguarda le persone che abbassano la testa nella sabbia dicendo che non influenza il set di caratteri che stanno usando oggi, beh, potresti usare quel set di caratteri oggi, ma il resto del mondo sta usando UTF-8 adesso e lo userete presto pure. Ricordati di scrivere come il tipo che mantiene il tuo codice è un maniaco omicida che sa dove vivi.

Oh, e come per i moduli Perl utilizzando \d rispetto a [0-9], anche il core ha ancora UNICODE problems.

Se si fa in realtà, qualsiasi cifra, ma vuole essere in grado di fare la matematica con i risultati, è possibile utilizzare 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"; 

Dopo un po 'di più il test sembra Text :: Unidecode doesn' t gestire correttamente tutti i caratteri numerici. Sto scrivendo un module che funzionerà.

44

Mi sembra molto pericoloso utilizzare \d, È una decisione di progettazione scadente nella lingua, come nella maggior parte dei casi si desidera [0-9]. La codifica di Huffman determinerebbe l'uso di \d per i numeri ASCII.

La maggior parte dei manifesti precedenti hanno già evidenziato il motivo per cui si dovrebbe usare [0-9], così mi permetta di darle un po 'più di dati:

  • Se ho letto bene '۷۰' le classifiche Unicode è un numero (70 in indicativo, non fidarti della mia parola per questo).

  • Prova questo:

    $ perl -le '$one = chr 0xFF11; print "$one + 1 = ", $one+1;' 
    1 + 1 = 1 
    
  • Ecco una lista parziale dei numeri validi (che può o non può mostrare correttamente nel browser, a seconda delle font usati), per ogni numero, solo il primo di coloro che vengono interpretati come un numero quando si fa aritmetica con Perl, come indicato sopra:

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

Sei ancora convinto?

+4

+1 per quella lista! Stavo cominciando a chiedermi quali altri personaggi numero ci fossero. – nickf

+1

Se Perl ha abbracciato UNICODE fino a questo punto, sembra che debba passare il resto e gestire tutte le cifre. Certo, in questo modo giace la follia, ma non è follia il destino di tutti i programmatori Perl ;-)? – RBerteig

+0

ci sono ancora più caratteri, ma ho incluso solo quelli che potrei visualizzare sul mio sistema. Ho usato i dati unicode da http://www.unicode.org/Public/UNIDATA/UnicodeData.txt e ho estratto le informazioni sui caratteri da lì. – mirod

1

Se [0-9] si ritiene goffo forse è possibile definire: $d=qr/[0-9]/; e utilizzare quello al posto di \d.

0

Come controlli formato dei dati salgono, la necessità per il modello di specificità va giù ...

esempio, se si sta corrispondono a un pezzo di dati che è stato generato macchina e segue sempre le stesse regole di formattazione di output, è non è necessario essere così precisi Prendere gli indirizzi IPv4. se si sta cercando di estrarre l'indirizzo IP da una linea di configurazione di interfaccia del router, tutti si ha realmente bisogno è qualcosa di simile:

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

SE, d'altra parte, si sta cercando di trovare un indirizzo IP incorporato in profondità da qualche parte in , per esempio, un'e-mail X-Header, o se stai provando a VALIDARE un indirizzo IP, beh ... questa è tutta un'altra storia!

Problemi correlati