GNU/Linux >> Linux Esercitazione >  >> Linux

Differenza tra [0-9], [[:digit:]] e D?

Nell'articolo di Wikipedia sulle espressioni regolari, sembra che [[:digit:]] =[0-9] =d .

Quali sono le circostanze in cui non sono uguali? Qual è la differenza?

Dopo alcune ricerche, penso che una differenza sia l'espressione tra parentesi [:expr:] dipende dalla locale.

Risposta accettata:

Sì, è [[:digit:]] ~ [0-9] ~ d (dove ~ significa approssimativo).
Nella maggior parte dei linguaggi di programmazione (dove è supportato)

d ≡ `[[:digit:]]`            # (is identical to, it is a short hand for).  

Il d esiste in meno casi di [[:digit:]] (disponibile in grep -P ma non in POSIX).

Cifre Unicode

Ci sono [molte cifre in UNICODE](http://www.fileformat.info/info/unicode/category/Nd/list.htm), ad esempio:

123456789 # Indù-arabo Numeri arabi
٠١٢٣٤٥٦٧٨٩ # ARABIC-INDIC
۰۱۲۳۴۵۶۷۸۹ # EXTENDED ARABIC-INDIC/PERSIAN
approssimati
०१२३४५६७८९ # DEVANAGARI

Tutto ciò può essere incluso in [[:digit:]] o d e anche alcuni casi di [0-9] .

POSIX

Per lo specifico POSIX BRE o ERE:
Il d non è supportato (non in POSIX ma è in GNU grep -P ). [[:cifra:]] è richiesto da POSIX per corrispondere alla classe di caratteri digit, che a sua volta è richiesto da ISO C per essere i caratteri da 0 a 9 e nient'altro. Quindi solo in lingua C tutti [0-9] , [0123456789] , d e [[:cifra:]] significa esattamente lo stesso. Il [0123456789] non ha possibili interpretazioni errate, [[:digit:]] è disponibile in più utilità e in alcuni casi significa solo [0123456789] . Il d è supportato da poche utilità.

Per quanto riguarda [0-9] , il significato delle espressioni di intervallo è definito solo da POSIX nella locale C; in altre località potrebbe essere diverso (potrebbe essere ordine codepoint o ordine di confronto o qualcos'altro).

[0123456789]

L'opzione più semplice per tutte le cifre ASCII.
Sempre valida, (AFAICT) nessuna istanza nota in cui non riesce.

Corrisponde solo alle cifre inglesi:0123456789 .

[0-9]

Si ritiene generalmente che [0-9] sono solo le cifre ASCII 0123456789 .
Questo è dolorosamente falso in alcuni casi:Linux in alcune impostazioni locali che non sono sistemi "C" (giugno 2020), ad esempio:

Supponiamo:

str='0123456789 ٠١٢٣٤٥٦٧٨٩ ۰۱۲۳۴۵۶۷۸۹ ߀߁߂߃߄߅߆߇߈߉ ०१२३४५६७८९'

Prova grep per scoprire che ne consente la maggior parte:

$ echo "$str" | grep -o '[0-9]+'
0123456789
٠١٢٣٤٥٦٧٨
۰۱۲۳۴۵۶۷۸
߀߁߂߃߄߅߆߇߈
०१२३४५६७८

Quel sed ha dei problemi. Dovrebbe rimuovere solo 0123456789 ma rimuove quasi tutte le cifre. Ciò significa che accetta la maggior parte delle cifre ma non alcuni nove (???):

$ echo "$str" | sed 's/[0-9]{1,}//g'
 ٩ ۹ ߉ ९

Che anche expr soffre degli stessi problemi di sed:

expr "$str" : '([0-9 ]*)'             # also matching spaces.
0123456789 ٠١٢٣٤٥٦٧٨

E anche nd

printf '%sn' 's/[0-9]/x/g' '1,p' Q | ed -v <(echo "$str")
105
xxxxxxxxxx xxxxxxxxx٩ xxxxxxxxx۹ xxxxxxxxx߉ xxxxxxxxx९

[[:cifra:]]

Esistono molti linguaggi:Perl, Java, Python, C. In cui [[:digit:]] (e d ) chiede un significato esteso. Ad esempio, questo codice Perl corrisponderà a tutte le cifre di cui sopra:

$ str='0123456789 ٠١٢٣٤٥٦٧٨٩ ۰۱۲۳۴۵۶۷۸۹ ߀߁߂߃߄߅߆߇߈߉ ०१२३४५६७८९'

$ echo "$str" | perl -C -pe 's/[^d]//g;' ; echo
0123456789٠١٢٣٤٥٦٧٨٩۰۱۲۳۴۵۶۷۸۹߀߁߂߃߄߅߆߇߈߉०१२३४५६७८९

Che equivale a selezionare tutti i caratteri che hanno le proprietà Unicode di Numeric e cifre :

$ echo "$str" | perl -C -pe 's/[^p{Nd}]//g;' ; echo
0123456789٠١٢٣٤٥٦٧٨٩۰۱۲۳۴۵۶۷۸۹߀߁߂߃߄߅߆߇߈߉०१२३४५६७८९

Quale grep potrebbe riprodurre (la versione specifica di pcre potrebbe avere un elenco interno di punti di codice numerico diverso rispetto a Perl):

$ echo "$str" | grep -oP 'p{Nd}+'
0123456789
٠١٢٣٤٥٦٧٨٩
۰۱۲۳۴۵۶۷۸۹
߀߁߂߃߄߅߆߇߈߉
०१२३४५६७८९

proiettili

Alcune implementazioni potrebbero interpretare un intervallo come qualcosa di diverso dal semplice ordine ASCII (ksh93 per esempio) (se testato nella versione di maggio 2018 (AT&T Research) 93u+ 2012-08-01):

$ LC_ALL=en_US.utf8 ksh -c 'echo "${1//[0-9]}"' sh "$str"
  ۹ ߀߁߂߃߄߅߆߇߈߉ ९

Ora (giugno 2020), lo stesso pacchetto ksh93 da debian (stessa versione sh (AT&T Research) 93u+ 2012-08-01):

$ LC_ALL=en_US.utf8 ksh -c 'echo "${1//[0-9]}"' sh "$str"

 ٩ ۹ ߉ ९

E questa mi sembra una fonte sicura di bug in attesa di verificarsi.

Correlati:la differenza tra gli operatori Bash [[ vs [ vs ( vs ((?
Linux
  1. La differenza tra [[ $a ==Z* ]] e [ $a ==Z* ]?

  2. Differenza tra utente Sudo e utente root?

  3. Differenza tra Snat e Masquerade?

  4. Differenza tra Qemu e KVM

  5. Differenza tra CLOCK_REALTIME e CLOCK_MONOTONIC?

Differenza tra apt e apt-get spiegato

La differenza tra Nss e Pam?

Differenza tra $HOME e '~' (tilde)?

differenza tra netstat e ss in linux?

Differenza tra ${} e $() in Bash

differenza tra cgroup e namespace