GNU/Linux >> Belajar Linux >  >> Linux

Perbedaan Antara [0-9], [[:digit:]] Dan D?

Dalam artikel Wikipedia tentang Ekspresi reguler, tampaknya [[:digit:]] =[0-9] =d .

Apa keadaan di mana mereka tidak sama? Apa bedanya?

Setelah beberapa penelitian, saya pikir satu perbedaan adalah ekspresi braket [:expr:] tergantung lokal.

Jawaban yang Diterima:

Ya, ini adalah [[:digit:]] ~ [0-9] ~ d (di mana ~ berarti perkiraan).
Di sebagian besar bahasa pemrograman (di mana didukung)

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

d ada dalam contoh yang lebih sedikit dari [[:digit:]] (tersedia di grep -P tetapi tidak dalam POSIX).

Digit Unicode

Ada [banyak digit dalam UNICODE](http://www.fileformat.info/info/unicode/category/Nd/list.htm), misalnya:

123456789 # Hindu-Arabic Angka Arab
٠١٢٣٤٥٦٧٨٩ # ARABIC-INDIC
۰۱۲۳۴۵۶۷۸۹ # EXTENDED ARABIC-INDIC/PERSIAN
߀߁߂߃߄߅߆߇߈߉ # NKO DIGIT
०१२३४५६७८९ # DEVANAGARI

Semuanya dapat dimasukkan dalam [[:digit:]] atau d , dan bahkan beberapa kasus [0-9] .

POSIX

Untuk POSIX BRE atau ERE tertentu:
d tidak didukung (tidak dalam POSIX tetapi dalam GNU grep -P ). [[:digit:]] diperlukan oleh POSIX agar sesuai dengan kelas karakter digit, yang pada gilirannya diperlukan oleh ISO C untuk menjadi karakter 0 hingga 9 dan tidak ada yang lain. Jadi hanya di C lokal semua [0-9] , [0123456789] , d dan [[:digit:]] berarti sama persis. [0123456789] tidak memiliki kemungkinan salah tafsir, [[:digit:]] tersedia di lebih banyak utilitas dan dalam beberapa kasus hanya berarti [0123456789] . d didukung oleh beberapa utilitas.

Adapun [0-9] , arti ekspresi rentang hanya ditentukan oleh POSIX di lokal C; di lokal lain mungkin berbeda (mungkin urutan codepoint atau urutan susunan atau yang lainnya).

[0123456789]

Opsi paling dasar untuk semua digit ASCII.
Selalu valid, (AFAICT) tidak ada contoh kegagalan yang diketahui.

Ini hanya cocok dengan Digit Bahasa Inggris:0123456789 .

[0-9]

Secara umum diyakini bahwa [0-9] hanya digit ASCII 0123456789 .
Itu sangat salah dalam beberapa kasus:Linux di beberapa lokal yang bukan sistem “C” (Juni 2020), misalnya:

Asumsikan:

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

Coba grep untuk mengetahui bahwa itu memungkinkan sebagian besar dari mereka:

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

Sed itu memiliki beberapa masalah. Sebaiknya hapus hanya 0123456789 tetapi menghapus hampir semua digit. Itu berarti ia menerima sebagian besar digit tetapi tidak menerima sembilan (???):

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

Bahkan expr menderita masalah yang sama dengan sed:

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

Dan juga ed

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

[[:digit:]]

Ada banyak bahasa:Perl, Java, Python, C. Di mana [[:digit:]] (dan d ) membutuhkan makna yang diperluas. Misalnya, kode perl ini akan cocok dengan semua digit dari atas:

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

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

Yang setara dengan memilih semua karakter yang memiliki properti Unicode Numeric dan digits :

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

grep mana yang dapat direproduksi (versi spesifik pcre mungkin memiliki daftar internal poin kode numerik yang berbeda dari Perl):

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

cangkang

Beberapa implementasi mungkin memahami rentang sebagai sesuatu yang berbeda dari urutan ASCII biasa (misalnya ksh93) (saat diuji pada versi Mei 2018 (Penelitian AT&T) 93u+ 2012-08-01):

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

 ٩ ۹ ߉ ९

Sekarang (Juni 2020), paket yang sama ksh93 dari debian (versi yang sama sh (AT&T Research) 93u+ 2012-08-01):

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

 ٩ ۹ ߉ ९

Dan itu menurut saya sebagai sumber pasti dari bug yang menunggu untuk terjadi.

Terkait:perbedaan antara operator Bash [[ vs [ vs ( vs ((?
Linux
  1. Perbedaan Antara Shell Login dan Shell Non-login?

  2. Perbedaan Antara 2>&-, 2>/dev/null, |&, &>/dev/null Dan>/dev/null 2>&1?

  3. Apa Perbedaan Antara Sudo Su – Dan Sudo Su —?

  1. Perbedaan Antara Eot dan Eof?

  2. Perbedaan Antara Aplikasi Gtk Dan Qt?

  3. Perbedaan Antara Ukuran Blok Dan Ukuran Cluster?

  1. Perbedaan Antara Snat dan Masquerade?

  2. Perbedaan antara $HOME dan '~' (tilde)?

  3. Perbedaan antara ${} dan $() di Bash