Im Wikipedia-Artikel über reguläre Ausdrücke scheint [[:digit:]]
=[0-9]
=d
.
Was sind die Umstände, wo sie nicht gleich sind? Was ist der Unterschied?
Nach einiger Recherche denke ich, dass ein Unterschied dieser Klammerausdruck [:expr:]
ist ist vom Gebietsschema abhängig.
Akzeptierte Antwort:
Ja, es ist [[:digit:]]
~ [0-9]
~ d
(wobei ~ ungefähr bedeutet).
In den meisten Programmiersprachen (wo es unterstützt wird)
d ≡ `[[:digit:]]` # (is identical to, it is a short hand for).
Das d
kommt weniger vor als [[:digit:]]
(verfügbar in grep -P
aber nicht in POSIX).
Unicode-Ziffern
Es gibt [viele Ziffern in UNICODE](http://www.fileformat.info/info/unicode/category/Nd/list.htm), zum Beispiel:
123456789 # Hindu-Arabic
Arabische Ziffern٠١٢٣٤٥٦٧٨٩ # ARABIC-INDIC
۰۱۲۳۴۵۶۷۸۹ # EXTENDED ARABIC-INDIC/PERSIAN
߀߁߂߃߄߅߆߇߈߉ # NKO DIGIT
०१२३४५६७८९ # DEVANAGARI
All dies kann in [[:digit:]]
enthalten sein oder d
, und sogar einige Fälle von [0-9]
.
POSIX
Für die spezifische POSIX BRE oder ERE:
Der d
wird nicht unterstützt (nicht in POSIX, aber in GNU grep -P
). [[:digit:]]
wird von POSIX benötigt, um der Ziffernzeichenklasse zu entsprechen, die wiederum von ISO C verlangt wird, um die Zeichen 0 bis 9 und sonst nichts zu sein. Also nur im Gebietsschema C alle [0-9]
, [0123456789]
, d
und [[:digit:]]
genau das gleiche bedeuten. Der [0123456789]
hat keine möglichen Fehlinterpretationen, [[:digit:]]
ist in mehr Dienstprogrammen verfügbar und bedeutet in einigen Fällen nur [0123456789]
. Das d
wird von wenigen Dienstprogrammen unterstützt.
Wie bei [0-9]
, die Bedeutung von Bereichsausdrücken wird nur von POSIX in der C-Locale definiert; in anderen Gebietsschemas kann es anders sein (möglicherweise Codepoint-Reihenfolge oder Kollatierungsreihenfolge oder etwas anderes).
[0123456789]
Die grundlegendste Option für alle ASCII-Ziffern.
Immer gültig, (AFAICT) kein bekannter Fall, wo es fehlschlägt.
Es stimmt nur mit englischen Ziffern überein:0123456789
.
[0-9]
Es wird allgemein angenommen, dass [0-9]
sind nur die ASCII-Ziffern 0123456789
.
Das ist in einigen Fällen schmerzlich falsch:Linux in einigen Gebietsschemas, die keine „C“-Systeme (Juni 2020) sind, zum Beispiel:
Angenommen:
str='0123456789 ٠١٢٣٤٥٦٧٨٩ ۰۱۲۳۴۵۶۷۸۹ ߀߁߂߃߄߅߆߇߈߉ ०१२३४५६७८९'
Versuchen Sie es mit grep
zu entdecken, dass es den meisten von ihnen erlaubt:
$ echo "$str" | grep -o '[0-9]+'
0123456789
٠١٢٣٤٥٦٧٨
۰۱۲۳۴۵۶۷۸
߀߁߂߃߄߅߆߇߈
०१२३४५६७८
Dieser Sed hat einige Probleme. Sollte nur 0123456789
entfernen aber entfernt fast alle Ziffern. Das bedeutet, dass es die meisten Ziffern akzeptiert, aber keine Neuner (???):
$ echo "$str" | sed 's/[0-9]{1,}//g'
٩ ۹ ߉ ९
Dieser sogar expr leidet unter den gleichen Problemen wie sed:
expr "$str" : '([0-9 ]*)' # also matching spaces.
0123456789 ٠١٢٣٤٥٦٧٨
Und auch Hrsg.
printf '%sn' 's/[0-9]/x/g' '1,p' Q | ed -v <(echo "$str")
105
xxxxxxxxxx xxxxxxxxx٩ xxxxxxxxx۹ xxxxxxxxx߉ xxxxxxxxx९
[[:Ziffer:]]
Es gibt viele Sprachen:Perl, Java, Python, C. In denen [[:digit:]]
(und d
) verlangt nach einer erweiterten Bedeutung. Zum Beispiel wird dieser Perl-Code mit allen Ziffern von oben übereinstimmen:
$ str='0123456789 ٠١٢٣٤٥٦٧٨٩ ۰۱۲۳۴۵۶۷۸۹ ߀߁߂߃߄߅߆߇߈߉ ०१२३४५६७८९'
$ echo "$str" | perl -C -pe 's/[^d]//g;' ; echo
0123456789٠١٢٣٤٥٦٧٨٩۰۱۲۳۴۵۶۷۸۹߀߁߂߃߄߅߆߇߈߉०१२३४५६७८९
Dies entspricht der Auswahl aller Zeichen mit den Unicode-Eigenschaften Numeric
und digits
:
$ echo "$str" | perl -C -pe 's/[^p{Nd}]//g;' ; echo
0123456789٠١٢٣٤٥٦٧٨٩۰۱۲۳۴۵۶۷۸۹߀߁߂߃߄߅߆߇߈߉०१२३४५६७८९
Welches grep reproduzieren könnte (die spezifische Version von pcre kann eine andere interne Liste numerischer Codepunkte haben als Perl):
$ echo "$str" | grep -oP 'p{Nd}+'
0123456789
٠١٢٣٤٥٦٧٨٩
۰۱۲۳۴۵۶۷۸۹
߀߁߂߃߄߅߆߇߈߉
०१२३४५६७८९
Muscheln
Einige Implementierungen verstehen einen Bereich möglicherweise als etwas anderes als die einfache ASCII-Reihenfolge (z. B. ksh93) (beim Testen in der Version vom Mai 2018 (AT&T Research) 93u+ 2012-08-01):
$ LC_ALL=en_US.utf8 ksh -c 'echo "${1//[0-9]}"' sh "$str"
۹ ߀߁߂߃߄߅߆߇߈߉ ९
Jetzt (Juni 2020), das gleiche Paket ksh93 von Debian (gleiche Version sh (AT&T Research) 93u+ 2012-08-01):
$ LC_ALL=en_US.utf8 ksh -c 'echo "${1//[0-9]}"' sh "$str"
٩ ۹ ߉ ९
Und das scheint mir eine sichere Quelle für Fehler zu sein, die darauf warten, passiert zu werden.
Verwandter:der Unterschied zwischen den Bash-Operatoren [[ vs [ vs ( vs ((?