wake-up-neo.net

Soll ich\d oder [0-9] verwenden, um die Ziffern in einem Perl Regex abzugleichen?

Nachdem ich in den letzten Wochen einige Fragen/Antworten gelesen hatte, habe ich gesehen, dass \d in regulären Ausdrücken von Perl als falsch eingestuft wurde. Wie in den späteren Versionen von Perl ist \d nicht das Gleiche wie [0-9], da \d jedes Unicode-Zeichen darstellt, das das Ziffernattribut besitzt, und [0-9] die Zeichen '0', '1', '2', ... '9'.

Ich weiß es zu schätzen, dass in einigen Kontexten [0-9] das richtige ist und in anderen \d. Ich habe mich gefragt, welche Leute glauben, dass die korrekte Standardeinstellung verwendet wird.

Ich persönlich finde die \d-Notation sehr knapp und ausdrucksstark, während [0-9] im Vergleich etwas umständlich ist. Ich habe jedoch wenig Erfahrung darin, mehrsprachigen Code zu erstellen, oder eher Code für Sprachen, die nicht in den ASCII - Zeichenbereich passen und daher naiv sein können.

Ich bemerke

$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

Für maximale Sicherheit empfehle ich die Verwendung von [0-9] immer dann, wenn Sie nicht ausdrücklich beabsichtigen, alle von Unicode definierten Ziffern abzugleichen.

Perldoc perluniintro , Perl unterstützt nicht die Verwendung von Ziffern außer [0-9] als Zahlen. Daher würde ich definitiv [0-9] verwenden, wenn beide zutreffend sind:

  1. Sie möchten das Ergebnis als Zahl verwenden (z. B. mathematische Operationen daran ausführen oder an einem Ort speichern, an dem nur richtige Zahlen akzeptiert werden (z. B. eine INT-Spalte in einer Datenbank)).

  2. Es ist möglich, dass [^0-9] in den Daten nicht-stellig ist, sodass der reguläre Ausdruck mit ihnen übereinstimmen könnte. (Beachten Sie, dass always für nicht vertrauenswürdige/feindliche Eingaben als wahr betrachtet werden sollte.)

Wenn beide falsch sind, gibt es nur selten einen Grund, nicht\d zu verwenden (und Sie können wahrscheinlich erkennen, wann dies der Fall ist) und ob Sie versuchen, Wenn Sie mit allen durch Unicode definierten Ziffern übereinstimmen, sollten Sie unbedingt \d verwenden.

38
Nicholas Knight

Es scheint mir sehr gefährlich zu sein, \d zu verwenden. Es ist eine schlechte Designentscheidung in der Sprache, da in den meisten Fällen [0-9] gewünscht wird. Eine Huffman-Codierung würde die Verwendung von \d für ASCII - Nummern vorschreiben. 

Die meisten der vorherigen Plakate haben bereits hervorgehoben, warum Sie [0-9] verwenden sollten. Lassen Sie mich Ihnen also etwas mehr Daten geben: 

  • Wenn ich die Unicode-Diagramme richtig gelesen habe, ist "۷۰" eine Zahl (70 in indikativ, nehmen Sie nicht mein Wort dafür).

  • Versuche dies: 

    $ Perl -le '$one = chr 0xFF11; print "$one + 1 = ", $one+1;'
    1 + 1 = 1
    
  • Hier ist eine unvollständige Liste gültiger Zahlen (die in Ihrem Browser je nach den verwendeten Schriftarten möglicherweise nicht richtig angezeigt werden). Für jede Zahl wird nur die erste Zahl als Zahl interpretiert, wenn Sie mit Arithmetik mit Perl arbeiten oben gezeigt:

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

Bist du immer noch nicht überzeugt?

52
mirod

Gemäß perlreref ist '\d' für das Gebietsschema geeignet und für Unicode geeignet.

Wenn es sich bei dem von Ihnen verwendeten Codesatz jedoch nicht um Unicode handelt, müssen Sie sich keine Gedanken über die Unicode-Ziffern machen. Dann schadet Ihnen das Gebietsschema-Bewusstsein auch nicht, da der Codesatz keine anderen Ziffern enthält.

Daher können Sie für viele Menschen '\d' meist ohne Bedenken verwenden. Wenn jedoch Unicode-Daten Teil Ihrer Arbeit sind, müssen Sie genauer überlegen, was Sie wollen.

8

Genauso wie die Website aus dem Orbit abgefeuert wird, ist [0-9] der einzige Weg, um sicher zu gehen. Ja, es ist hässlich. Ja, die Wahl, \d UNICODE und das Gebietsschema bewusst zu machen, war dumm. Aber das ist unser Bett und wir müssen drin liegen.

Die Leute, die ihren Kopf in den Sand stecken und sagen, dass sie den heute verwendeten Zeichensatz nicht beeinflussen, können Sie diesen Zeichensatz heute verwenden, aber der Rest der Welt verwendet jetzt UTF-8 und Sie werden es auch es auch bald verwenden. Denken Sie daran, wie der Kerl, der Ihren Code aufrechterhält, ein mörderischer Wahnsinniger ist, der weiß, wo Sie leben.

Und was Perl-Module mit \d vs. [0-9] anbelangt, so hat sogar der Kern noch UNICODE-Probleme .

Wenn Sie tatsächlich eine Ziffer meinen, aber mit den Ergebnissen rechnen möchten, können Sie Text::Unidecode verwenden:

#!/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";

Nach einigen weiteren Tests sieht es so aus, als würde Text :: Unidecode nicht alle Ziffern korrekt verarbeiten. Ich schreibe ein Modul das funktioniert.

5
Chas. Owens

Ich habe das Gefühl, dass beide ihren Platz haben müssen. Sie sind jedoch zu 99,999% der Zeit (besonders in meiner geschlossenen großen amerikanischen Kooperationswelt) austauschbar. Ich verwende Perl, um täglich Daten zu bearbeiten. In keinem der Datensätze, mit denen ich zu tun habe, gibt es Zahlen, die nicht in [0-9] passen. Ich bin mir jedoch bewusst, dass es einen wichtigen Unterschied zwischen \d und[0-9] gibt, und es ist gut, sich dieses Unterschieds bewusst zu sein. Ich benutze \d, weil es (wie Sie sagten) prägnanter erscheint und in meiner kleinen Welt der Datenmanipulation niemals "falsch" wäre.

3
Copas

Wenn Sie \d auf eine Unicode-Zeichenfolge anwenden (z. B. in "\X{660}" =~ /\d/), stimmt diese mit einer Unicode-Ziffer überein. Wenn Sie \d auf eine binäre Zeichenfolge anwenden (z. B. das UTF-8-Äquivalent des obigen Befehls: "\xd9\xa0" =~ /\d/), werden nur die 10 ASCII -Ziffern verwendet. Perl 5.8 erstellt standardmäßig keine Unicode-Zeichenfolgen (es sei denn, Sie werden ausdrücklich danach gefragt, z. B. in "\X{...}" oder use utf8; usw.).

Mein Tipp ist also: Achten Sie nur auf den Unterschied zwischen \d und [0-9], wenn Ihre Anwendung Unicode-Zeichenfolgen verwendet.

2
pts

Wenn sich [0-9] etwas unbeholfen anfühlt, könnten Sie Folgendes definieren: $d=qr/[0-9]/; und anstelle von \d verwenden.

1
Mattias

Da die Datenformatkontrollen steigen, sinkt die Notwendigkeit der Musterspezifität ...

Wenn Sie beispielsweise mit einem maschinengenerierten Datenelement übereinstimmen, das immer den gleichen Regeln für die Ausgabeformatierung folgt, müssen Sie nicht so präzise sein. _ Nehmen Sie IPv4-Adressen. Wenn Sie versuchen, die IP-Adresse aus einer Router-Schnittstellenkonfigurationszeile zu extrahieren, benötigen Sie lediglich Folgendes:

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

WENN Sie dagegen versuchen, eine tief in einem E-Mail-X-Header eingebettete IP-Adresse zu finden, oder wenn Sie versuchen, eine IP-Adresse zu BESTÄTIGEN, dann ist das eine ganz andere Geschichte!

0
skeetastax