[0-9], [[अंक:]] और \ d के बीच अंतर


35

में रेगुलर एक्सप्रेशन पर विकिपीडिया लेख , ऐसा लगता है कि [[:digit:]]= [0-9]= \d

ऐसी कौन सी परिस्थितियाँ हैं जहाँ वे बराबर नहीं हैं? अंतर क्या है?

कुछ शोध के बाद, मुझे लगता है कि एक अंतर यह है कि ब्रैकेट अभिव्यक्ति [:expr:]स्थानीय निर्भर है।


3
क्या आप अपने प्रश्न का उत्तर देने के लिए विकिपीडिया लेख से नहीं जुड़े हैं ? विभिन्न नियमित अभिव्यक्ति प्रोसेसर / इंजन चरित्र वर्गों (अन्य चीजों के बीच) के लिए अलग वाक्यविन्यास का समर्थन करते हैं।
alगल

@igal wiki का कहना है कि अंतर है लेकिन बहुत विस्तार नहीं देता है। मैं विस्तार से पूछ रहा हूँ, इसहाक की तरह कुछ, thrig ने कहा। मुझे grep, sed, awk में उनके अंतर में बहुत दिलचस्पी है ... जीएनयू संस्करण है या नहीं।
हार्बिन

जवाबों:


40

हां, यह [[:digit:]]~ [0-9]~ है \d(जहां ~ का मतलब है अनुलोम विलोम)।
सबसे प्रोग्रामिंग भाषाओं (जहां यह समर्थित है) में \d[[:digit:]](समान)।
की \dतुलना में कम सामान्य है [[:digit:]](POSIX में नहीं है लेकिन यह GNU में है grep -P)।

उदाहरण के लिए, UNICODE में कई अंक हैं :

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

जो सब के सब शामिल किया जा सकता में [[:digit:]]या \d

इसके बजाय, [0-9]आम तौर पर केवल ASCII अंक होते हैं 0123456789


कई भाषाएं हैं: पर्ल, जावा, पायथन, सी। जिसमें [[:digit:]](और \d) विस्तारित अर्थ के लिए कॉल करता है। उदाहरण के लिए, यह पर्ल कोड ऊपर से सभी अंकों से मेल खाएगा:

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

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

जो उन सभी वर्णों का चयन करने के लिए समान है जिनमें यूनिकोड के गुण हैं Numericऔर digits:

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

किस grep को पुन: उत्पन्न किया जा सकता है (पीसीआर के विशिष्ट संस्करण में पर्ल की तुलना में संख्यात्मक कोड बिंदुओं की एक अलग आंतरिक सूची हो सकती है):

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

इसे देखने के लिए [0-9] में बदलें:

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

POSIX

विशिष्ट POSIX BRE या ERE के लिए: (इसे POSIX में नहीं बल्कि जीएनयू में है समर्थित नहीं है )। POSIX द्वारा डिजिट कैरेक्टर क्लास के अनुरूप होना आवश्यक है, जिसके बदले ISO C को अक्षर 0 से 9 होना चाहिए और कुछ नहीं। तो केवल सी में स्थान में सब , , और बिल्कुल वैसा ही मतलब है। कोई संभव गलत व्याख्याओं है, अधिक उपयोगिताओं में उपलब्ध है और यह केवल मतलब के लिए आम है । कुछ उपयोगिताओं द्वारा समर्थित है।
\dgrep -P[[:digit:]][0-9][0123456789]\d[[:digit:]][0123456789][[:digit:]][0123456789]\d

के रूप में [0-9], श्रेणी के भाव का अर्थ केवल सी लोकेल में पोसिक्स द्वारा परिभाषित किया गया है; अन्य स्थानों में यह अलग हो सकता है (कोडपॉइंट ऑर्डर या कोलाजेशन ऑर्डर या कुछ और हो सकता है)।

गोले

कुछ कार्यान्वयन सादे ASCII आदेश (उदाहरण के लिए ksh93) की तुलना में कुछ अलग होने की सीमा को समझ सकते हैं:

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

और यह बग का एक निश्चित स्रोत है।


POSIX सिस्टम पर अभ्यास में, iswctype()और POSIX उपयोगिताओं में BRE / ERE / वाइल्डकार्ड, [0-9] और [[अंक:]] केवल 0123456789 पर मेल खाते हैं। और यह मानक के अगले संशोधन में स्पष्ट किया जाएगा
स्टीफन चेज़लस

मैं बारे में पता नहीं था कि perl's \dअन्य लिपियों से दशमलव अंक पर मिलान यूनिकोड मोड में। उसके लिए धन्यवाद। PCRE के साथ, (*UCP)GNU के रूप में grep -Po '(*UCP)\d'या grep -Po '(*UCP)[[:digit:]]यूनिकोड गुणों पर आधारित कक्षाओं के लिए देखें।
स्टीफन चेज़ेलस

मैं सहमत हूं कि [:digit:]वाक्यविन्यास सुझाव देगा कि आप स्थानीयकरण का उपयोग करना चाहते हैं, यही वह है जो उपयोगकर्ता एक अंकों के रूप में मानता है। मैं कभी भी उपयोग नहीं करता [:digit:]क्योंकि व्यवहार में वही [0-9]और किसी भी मामले में, हमेशा मैं 0123456789 पर मेल खाना चाहता हूं, मेरा मतलब कभी भी मैच नहीं करना है ٠١٢٣٤٥٦٧٨٩, और मैं एक उपयोग के मामले के बारे में नहीं सोच सकता जहां कोई दशमलव अंक पर मिलान करना चाहेगा POSIX उपयोगिताओं के साथ किसी भी स्क्रिप्ट में। Zsh ML पर वर्तमान चर्चा[:blank:] भी देखें । वे चरित्र वर्ग थोड़े गड़बड़ हैं।
स्टीफन चेज़ेलस

13

यह इस बात पर निर्भर करता है कि आप किसी अंक को कैसे परिभाषित करते हैं; [0-9]केवल ASCII वाले होते हैं (या संभवतः कुछ और है जो न तो ASCII है और न ही ASCII का सुपरसेट है, लेकिन ASCII में समान 10 अंक केवल विभिन्न बिट अभ्यावेदन (EBCDIC) के साथ हैं); \dदूसरी ओर या तो सिर्फ सादे अंक (पर्ल के पुराने संस्करण, या /aनियमित अभिव्यक्ति ध्वज सक्षम के साथ पर्ल के आधुनिक संस्करण ) हो सकते हैं या यह एक यूनिकोड मैच हो सकता है, \p{Digit}जो [0-9]या /\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 अधिक जानकारी के लिए, या यह देखने के लिए कि यह कैसे व्यवहार करता है, भाषा के लिए प्रलेखन से परामर्श करें।

लेकिन रुकिए, और भी है! लोकेल भी अलग-अलग हो सकता है \d, जो मेल खाता है, इसलिए \dइस तरह के पूर्ण यूनिकोड सेट की तुलना में कम अंक मिलान कर सकते हैं, और (उम्मीद है, आमतौर पर) भी शामिल हैं [0-9]। यह C के बीच अंतर के समान है isdigit(3)( [0-9]) और isnumber(3)( [0-9साथ ही लोकल से जो भी हो)।

ऐसे कॉल हो सकते हैं जो अंकों के मूल्य को प्राप्त करने के लिए किए जा सकते हैं, भले ही यह न हो [0-9]:

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

मुझे लगता isnumber()है कि यह एक बीएसडी चीज है, कम से कम उस आदमी के पेज पर आधारित है जो ऐसा लगता है
ilkachachu

मेरे पास बीएसडी पूर्वाग्रह के कुछ है, हां
थ्रान

/ झंडा केवल मैच के लिए यूनिकोड अंकों की सूची को कम करने के लिए एक विशिष्ट सीमक है ... / a संशोधक का उपयोग केवल 9 के माध्यम से ASCII 0 से मेल खाने के लिए मजबूर करने के लिए किया जा सकता है । जैसे, यह केवल और केवल एक ही मैच के लिए मजबूर कर रहा है [0-9]
इसहाक

5

के विभिन्न अर्थ [0-9], [[:digit:]]और \dअन्य उत्तरों में प्रस्तुत किए गए हैं। यहां मैं रेगेक्स इंजन के कार्यान्वयन में अंतर जोड़ना चाहूंगा।

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

इसलिए [[:digit:]]हमेशा काम करता है , \dनिर्भर करता है। ग्रेप मैनुअल में यह उल्लेख किया गया है कि [[:digit:]]बस 0-9में Cस्थान।

PS1: यदि आप अधिक जानते हैं, तो कृपया तालिका का विस्तार करें।

PS2: GNU grep 3.1 और GNU 4.4 परीक्षण के लिए उपयोग किया जाता है।


2
1) जीएनयू संस्करणों बनाम दूसरों के बीच सबसे बड़े अंतर के साथ grepऔर कई संस्करण sedहैं। यह उत्तर अधिक उपयोगी हो सकता है यदि यह उल्लेख किया जाए कि यह किस संस्करण का है grepऔर sedइसका संदर्भ है। या उस तालिका का स्रोत क्या है, इस बात के लिए। 2) उस तालिका को भी पाठ में स्थानांतरित किया जा सकता है, क्योंकि इसमें ऐसी कोई भी चीज़ नहीं है जिसके लिए एक छवि की आवश्यकता हो
ilkachachu

@ilkachachu 1) नवीनतम GNU grep 3.1 और GNU 4.4 परीक्षण के लिए उपयोग किया जाता है। 2) मैं टेबल बनाने का तरीका नहीं जानता। ऐसा लगता है कि @ मूरू ने तालिका को एक सुंदर पाठ के रूप में बदल दिया है।
हरबिन

@harbinn कृपया अपने उत्तर में संपादित करें।
दान डी।

@DanD। संस्करण जानकारी जोड़ा गया। ध्यान के लिए thx
हार्बिन

1
ध्यान दें कि reमॉड्यूल में बनाया गया अजगर [[अंक:]] का समर्थन नहीं करता है, लेकिन पुस्तकालय में ऐड regexइसका समर्थन करता है इसलिए मैं हमेशा काम करता है पर थोड़ा निगलेगा। यह हमेशा पॉजिक्स की शिकायत स्थितियों में काम करता है।
स्टीव बार्न्स

4

सैद्धांतिक अंतर पहले से ही अन्य उत्तरों में बहुत अच्छी तरह से समझाया गया है, इसलिए यह व्यावहारिक अंतरों की व्याख्या करने के लिए बना हुआ है ।

अंकों के मिलान के लिए कुछ अधिक सामान्य उपयोग के मामले यहां दिए गए हैं:


एक-शॉट डेटा निष्कर्षण

अक्सर, जब आप कुछ संख्याओं को क्रंच करना चाहते हैं, तो संख्याएं स्वयं एक अजीब रूप से स्वरूपित पाठ फ़ाइल में होती हैं। आप उन्हें अपने कार्यक्रम में उपयोग के लिए निकालना चाहते हैं। आप संभवतः संख्या प्रारूप (फ़ाइल को देखकर) और अपने वर्तमान स्थान को बता सकते हैं, इसलिए किसी भी रूप का उपयोग करना ठीक है , जब तक कि यह काम नहीं करता है। \dसबसे कम कीस्ट्रोक्स की आवश्यकता होती है, इसलिए इसका उपयोग आमतौर पर किया जाता है।

इनपुट सैनिटाइजिंग

आपके पास कुछ अविश्वसनीय उपयोगकर्ता इनपुट है (शायद वेब फ़ॉर्म से), और आपको यह सुनिश्चित करने की आवश्यकता है कि इसमें कोई आश्चर्य नहीं है। हो सकता है कि आप इसे डेटाबेस में एक संख्यात्मक क्षेत्र में संग्रहीत करना चाहते हैं, या सर्वर पर चलाने के लिए शेल कमांड के पैरामीटर के रूप में उपयोग करना चाहते हैं। इस मामले में, आप वास्तव में चाहते हैं [0-9], क्योंकि यह सबसे अधिक प्रतिबंधात्मक और पूर्वानुमान योग्य है।

डेटा मान्य

आपके पास थोड़ा सा डेटा है जिसे आप किसी भी "खतरनाक" के लिए उपयोग नहीं करने जा रहे हैं, लेकिन यह जानना अच्छा होगा कि क्या यह एक नंबर है। उदाहरण के लिए, आपका प्रोग्राम उपयोगकर्ता को एक पता इनपुट करने की अनुमति देता है, और आप एक संभावित टाइपो को उजागर करना चाहते हैं यदि इनपुट में कोई मकान नंबर नहीं है। इस मामले में, आप शायद जितना संभव हो उतना व्यापक होना चाहते हैं, इसलिए [[:digit:]]जाने का रास्ता है।


उन अंकों के मिलान के लिए तीन सबसे आम उपयोग के मामले प्रतीत होंगे। अगर आपको लगता है कि मैं एक महत्वपूर्ण चूक गया, तो कृपया एक टिप्पणी छोड़ दें।


अच्छी नौकरी, सुरक्षा संबंधी समस्या, जैसे कि ReDoS या अन्य
frams
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.