GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Unterschied zwischen [0-9], [[:digit:]] und D?

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 ((?
Linux
  1. Unterschied zwischen Login-Shell und Nicht-Login-Shell?

  2. Unterschied zwischen 2>&-, 2>/dev/null, |&, &>/dev/null und>/dev/null 2>&1?

  3. Was ist der Unterschied zwischen Sudo Su – und Sudo Su –?

  4. Unterschied zwischen Eot und Eof?

  5. Unterschied zwischen Blockgröße und Clustergröße?

Unterschied zwischen apt und apt-get erklärt

Der Unterschied zwischen Nss und Pam?

Unterschied zwischen $HOME und '~' (Tilde)?

unterschied zwischen netstat und ss unter linux?

Unterschied zwischen ${} und $() in Bash

Unterschied zwischen Cgroups und Namespaces