[0-9], [[: digit:]] ve \ d arasındaki fark


35

Gelen Düzenli ifadeler Vikipedi'ye , bu gibi görünüyor [[:digit:]]= [0-9]= \d.

Eşit olmadıkları koşullar nelerdir? Fark ne?

Bazı araştırmalardan sonra, bir farkın parantez ifadesinin [:expr:]yerel ayara bağlı olduğunu düşünüyorum .


3
Yok mu sen bağlantılı olduğu Wikipedia makalesi sorunuza cevap? Farklı düzenli ifade işlemcileri / motorları karakter sınıfları için farklı sözdizimlerini destekler (diğer şeylerin yanı sıra).
igal,

@igal wiki, fark olduğunu ancak fazla ayrıntı vermediğini söylüyor. Ayrıntıları soruyorum, isaac gibi bir şey, dedi trig. GNU versiyonunda olsun olmasın, grep, sed, awk… arasındaki farklarla oldukça ilgiliyim.
18'de harbinn

Yanıtlar:


40

Evet, öyle [[:digit:]]~ [0-9]~ \d(burada ~ vasıta aproximate).
Çoğu programlama dilinde (desteklendiği yerde) \d[[:digit:]](aynı). Daha az yaygındır (POSIX ama GNU içinde olduğunu ).
\d[[:digit:]]grep -P

UNICODE'de birçok rakam var, örneğin:

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

Bunların tümü veya içerisinde bulunabilir .[[:digit:]]\d

Bunun yerine, [0-9]genellikle yalnızca ASCII basamaktır 0123456789.


Pek çok dil var: Perl, Java, Python, C İçinde genişletilmiş bir anlam ifade eden [[:digit:]](ve \d). Örneğin, bu perl kodu yukarıdan gelen tüm rakamlarla eşleşecektir:

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

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

Unicode özelliklerine sahip tüm karakterleri seçmek için eşdeğerdir Numericve digits:

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

Hangi grep yeniden üretilebilir (pcre'nin özel sürümü Perl'den farklı bir sayısal kod noktaları listesi içerebilir):

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

Görmek için [0-9] olarak değiştirin:

$ echo "$a" | grep -o '[0-9]\+'
0123456789

POSIX

Spesifik POSIX BRE veya ERE için: (POSIX ama GNU'da olan desteklenmez ). POSIX tarafından sayısal karakter sınıfına karşılık gelmesi gerekir; bu da ISO C tarafından 0 - 9 arasındaki karakterlerden başka bir şey değildir. Yani sadece C yerele tüm , , ve tam olarak aynı anlama. Hiçbir olası yanlış yorumlamaları vardır fazla yardımcı programlar mevcuttur ve sadece anlama yaygındır . Birkaç kamu tarafından desteklenmektedir.
\dgrep -P[[:digit:]][0-9][0123456789]\d[[:digit:]][0123456789][[:digit:]][0123456789]\d

İçin olduğu gibi [0-9], sadece C yereli POSIX'e ile tanımlanır aralık ifadelerinin anlamı; diğer yerlerde farklı olabilir (kod noktası sırası veya harmanlama sırası veya başka bir şey olabilir).

kabuklar

Bazı uygulamalar bir seriyi ASCII düzenden farklı bir şey olarak anlayabilir (örneğin, ksh93):

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

Ve bu, gerçekleşmeyi bekleyen bir böcek kaynağı.


POSIX sistemlerindeki pratikte iswctype()ve POSIX yardımcı programlarındaki BRE / ERE / joker karakterler, [0-9] ve [[: digit:]] yalnızca 0123456789 ile eşleşir. Ve bu, standardın bir sonraki revizyonunda açıklanacak
Stéphane Chazelas,

O değil farkındaydı perl's \ddiğer komut ondalık basamak eşleşen Unicode modunda. Bunun için teşekkürler. PCRE ile, GNU'daki (*UCP)gibi grep -Po '(*UCP)\d'veya grep -Po '(*UCP)[[:digit:]]Unicode özelliklerine dayalı sınıflar için görün.
Stéphane Chazelas 15:18

[:digit:]Sözdiziminin, yerelleştirmeyi kullanmak istediğinizi, kullanıcı rakam olarak gördüğü şeyin bu olduğunu kabul edeceğini kabul ediyorum . Hiç kullanmıyorum, [:digit:]çünkü pratikte [0-9]her durumda olduğu gibi ve aynı , her zaman 0123456789'da eşleştirmek istiyorum, hiçbir zaman eşleşmek ٠١٢٣٤٥٦٧٨٩istemiyorum ve birinin ondalık basamakta eşleşmek isteyeceği bir kullanım durumu düşünemiyorum POSIX yardımcı programlarıyla herhangi bir komut dosyasında. Ayrıca, zsh ML hakkındaki güncel tartışmaya[:blank:] bakın . Bu karakter sınıfları biraz dağınık.
Stéphane Chazelas 15:18

13

Bu rakamı nasıl tanımladığınıza bağlıdır; [0-9]sadece ASCII olanlar olma eğilimindedir (veya ASCII'nin veya ASCII'nin bir üstkümesi olmayan ancak ASCII'deki aynı 10 hane yalnızca farklı bit gösterimleri (EBCDIC) olan başka bir şey olma eğilimindedir; \dÖte yandan, sadece basit rakamlar (Perl'in eski versiyonları veya /anormal ifade bayrağının etkin olduğu Perl’in modern versiyonları ) olabilir veya Unicode eşleşmesi, \p{Digit}daha büyük rakamlardan oluşan [0-9]veya onlardan daha büyük olan bir Unicode eşleşmesi olabilir /\d/a.

$ perl -E 'say "match" if 42 =~ m/\d/'
match
$ perl -E 'say "match" if "\N{U+09EA}" =~ m/\d/'
match
$ perl -E 'say "match" if "\N{U+09EA}" =~ m/\d/a'
$ perl -E 'say "match" if "\N{U+09EA}" =~ m/[0-9]/'
$ 

perldoc perlrecharclass Daha fazla bilgi için veya nasıl davrandığını görmek için söz konusu dilin belgelerine bakın.

Ama bekleyin, dahası var! Yerel ayar, hangi \deşleşmeleri de değiştirebilir ; bu nedenle \d, Unicode kümesinin tamamından daha az rakamla eşleşebilir ve (umarım genellikle de) [0-9]. Bu, isdigit(3)( [0-9]) ve isnumber(3)( [0-9artı yerel ayarlardan başka ne olursa olsun ) arasındaki C farkına benzer .

Rakamın değerini almak için yapılabilecek aramalar olabilir, olmasa bile [0-9]:

$ perl -MUnicode::UCD=num -E 'say num(4)'
4
$ perl -MUnicode::UCD=num -E 'say num("\N{U+09EA}")'
4
$ 

Ben isnumber()bir BSD şey olduğunu düşünüyorum , en azından göründüğü adam sayfasına göre
ilkkachu

Evet, bir BSD önyargı şey var
thrig

/ A bayrağı, yalnızca eşleşecek Unicode rakamlarının listesini azaltmak için belirli bir sınırlayıcıdır … / a değiştiricisi, yalnızca ASCII 0 - 9 ile eşleşmeye zorlamak için kullanılabilir . Bu nedenle, tamamen aynı ve sadece eşleşmeye zorlanıyor [0-9].
Isaac

5

Farklı bir anlam [0-9], [[:digit:]]ve \ddiğer yanıtlar sunulmaktadır. Burada regex motorunun uygulanmasında farklılıklar eklemek istiyorum.

            [[:digit:]]    \d
grep -E               ✓     ×
grep -P               ✓     ✓
sed                   ✓     ×
sed -E                ✓     ×

Yani [[:digit:]]her zaman çalışır , \dbağlıdır. Grep'in el kitabında [[:digit:]]sadece yerel ayarlarda 0-9olduğu Csöylenir.

PS1: Daha fazlasını biliyorsanız, lütfen tabloyu genişletin.

PS2: GNU grep 3.1 ve GNU 4.4 test için kullanılır.


2
1) Orada birçok versiyonu olduğunu grepve sedmuhtemelen diğerleri vs GNU sürümleri arasındaki en büyük fark,. O hangi sürümünü bahsetti Bu cevap daha yararlı olabilir grepve sedbunun ifade eder. Veya bu tablonun kaynağının ne olduğuna bağlı olarak. 2) bu tablo metne dönüştürülebilir, çünkü resim olmasını gerektiren hiçbir şey içermez
ilkkachu 14

@ilkkachu 1) En son GNU grep 3.1 ve GNU 4.4 test için kullanılır. 2) Nasıl masa oluşturulacağını bilmiyorum. @ Muru, masayı güzel bir metin şekline dönüştürmüş gibi görünüyor.
18'de harbinn

@harbinn Lütfen cevabınızı düzenleyin.
Dan D.

@DanD. sürüm bilgisi eklendi. dikkat için thx
harbinn

1
Modülde yerleşik olan python'un re[[: digit:]] desteklemediğini, ancak kütüphanedeki eklentinin regexonu desteklediğini unutmayın, böylece her zaman işe yarayan biraz kıkırdatacağım. Her zaman posix şikayet durumlarında çalışır.
Steve Barnes

4

Teorik farklar, diğer cevaplarda zaten oldukça iyi açıklanmıştır, bu nedenle pratik farkları açıklamak için kalır .

Bir basamağı eşleştirmek için kullanılan yaygın kullanım durumlarından bazıları:


Tek atış veri çıkarma

Genelde, bazı numaraları sıkıştırmak istediğinizde, numaraların kendileri garip bir biçimde biçimlendirilmiş bir metin dosyasındadır. Bunları programınızda kullanmak üzere çıkarmak istiyorsunuz. Muhtemelen sayı biçimini (dosyaya bakarak) ve şu anki yerel ayarlarınızı söyleyebilirsiniz, bu nedenle , işi aldığı sürece herhangi bir form kullanmanız uygundur . \den az tuşa basılmasını gerektirir, bu yüzden çok sık kullanılır.

Giriş temizliği

Bazı güvenilir olmayan kullanıcı girişleriniz var (belki bir web formundan) ve herhangi bir sürpriz içermediğinden emin olmalısınız. Belki bir veritabanında sayısal bir alanda saklamak veya bir sunucuda çalıştırmak için kabuk komutuna parametre olarak kullanmak istiyorsunuz. Bu durumda, gerçekten istiyorsun [0-9], çünkü en kısıtlayıcı ve tahmin edilebilir olanı.

Veri doğrulama

Tehlikeli bir şey için kullanmayacağınız bir miktar veriye sahipsiniz, ancak sayı olup olmadığını bilmek güzel olurdu. Örneğin, programınız kullanıcının bir adres girmesine izin verir ve giriş bir ev numarası içermiyorsa olası bir yazım hatasını vurgulamak istersiniz. Bu durumda, muhtemelen mümkün olduğu kadar geniş [[:digit:]]olmak istersiniz, bu şekilde gitmenin yolu da öyle .


Bunlar rakam eşleştirme için en yaygın üç kullanım durumu olarak görünmektedir. Önemli bir şeyi kaçırdığımı düşünüyorsanız, lütfen bir yorum bırakın.


iyi iş, ReDoS veya diğerleri gibi güvenlikle ilgili bir sorun mu var
0
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.