नियमित अभिव्यक्ति वास्तव में कैसे काम करती है?


30

कहें कि आपके पास एक निबंध लिखा हुआ दस्तावेज है। आप इस निबंध को केवल कुछ शब्दों का चयन करना चाहते हैं। ठंडा।

एक मैच की तलाश में शब्द द्वारा लाइन और शब्द द्वारा फ़ाइल लाइन को पार्स करने की तुलना में एक नियमित अभिव्यक्ति का उपयोग करना तेजी से है? यदि ऐसा है, तो यह कैसे काम करता है? आप प्रत्येक शब्द को देखने की तुलना में तेजी से कैसे जा सकते हैं?


5
आप मान लेते हैं (शून्य साक्ष्य लगाना) कि एक नियमित अभिव्यक्ति जल्दी हो जाएगी, लेकिन आप नहीं जानते कि यह क्यों है? शायद आपको अपनी धारणा पर पुनर्विचार करना चाहिए।
पीडीआर

3
इस प्रकार, धारणा। अगर मेरे पास सबूत होता, तो वह एक नहीं होता, है ना?
lazeR

4
ये मुद्दा नहीं है। बिंदु वह है जो आपको उस धारणा तक ले जाता है ... आपको अपने प्रश्नों के प्रमाण की आवश्यकता नहीं है, लेकिन आपको अपनी मान्यताओं के तर्क की आवश्यकता है।
यानिस ३०'११

1
गलत तरीके से, इनपुट स्ट्रिंग के प्रत्येक चरित्र को केवल एक राज्य मशीन को अगले राज्य में स्थानांतरित नहीं किया जा रहा है। मैं यह नहीं देख सकता कि कोई भी उस ऑपरेशन को धीमा कैसे कर सकता है ...
tp1

2
मुझे जल्दी पता नहीं है, लेकिन नियमित अभिव्यक्ति का उपयोग करने का मेरा मुख्य कारण जटिल मिलान पैटर्न की लालित्य के कारण है, आप बस इसे कोडिंग वातावरण में व्यक्त करने का एक बेहतर तरीका नहीं पाएंगे।
मंटोरोक 10

जवाबों:


47

यह कैसे काम करता है?

ऑटोमेटा सिद्धांत पर एक नज़र डालें

संक्षेप में, प्रत्येक नियमित अभिव्यक्ति में एक समान परिमित ऑटोमेटन होता है और इसे परिमित ऑटोमेटन के लिए संकलित और अनुकूलित किया जा सकता है। शामिल एल्गोरिदम कई संकलक पुस्तकों में पाए जा सकते हैं। ये एल्गोरिदम यूनिक्स प्रोग्राम जैसे कि awk और grep द्वारा उपयोग किए जाते हैं।

हालांकि, अधिकांश आधुनिक प्रोग्रामिंग भाषाएं (पर्ल, पायथन, रूबी, जावा (और जेवीएम आधारित भाषाएं), सी #) इस दृष्टिकोण का उपयोग नहीं करती हैं। वे एक पुनरावर्ती बैकट्रैकिंग दृष्टिकोण का उपयोग करते हैं, जो एक पेड़ में एक नियमित अभिव्यक्ति या नियमित अभिव्यक्ति के विभिन्न उपखंडों का प्रतिनिधित्व करने वाले निर्माणों के अनुक्रम को संकलित करता है। अधिकांश आधुनिक "नियमित अभिव्यक्ति" वाक्यविन्यास बैकरेफरेंस प्रदान करते हैं जो नियमित भाषाओं के समूह के बाहर हैं (उनका परिमित ऑटोमेटा में कोई प्रतिनिधित्व नहीं है), जो पुनरावर्ती दृष्टिकोण में तुच्छ रूप से लागू होते हैं।

अनुकूलन आमतौर पर एक अधिक कुशल राज्य मशीन का उत्पादन करता है। उदाहरण के लिए: आआआब | आआआक | अआअद पर विचार करें। एक सामान्य प्रोग्रामर को सरल लेकिन कम कुशल खोज कार्यान्वयन (अलग से तीन तार की तुलना) दस मिनट में मिल सकता है। लेकिन यह एहसास आआआ [bcd] के बराबर है, पहले चार 'a' को खोजकर एक बेहतर खोज की जा सकती है, फिर [b, c, d] के विरुद्ध 5 वें वर्ण का परीक्षण करें। अनुकूलन की प्रक्रिया कई वर्षों पहले मेरे संकलक गृह कार्य में से एक थी इसलिए मुझे लगता है कि यह सबसे आधुनिक नियमित अभिव्यक्ति इंजन में भी है।

दूसरी ओर, राज्य मशीनों को कुछ लाभ होता है जब वे तार को स्वीकार कर रहे होते हैं क्योंकि वे "तुच्छ कार्यान्वयन" की तुलना में अधिक स्थान का उपयोग करते हैं। SQL स्ट्रिंग्स पर उद्धरण से बचने के लिए एक कार्यक्रम पर विचार करें, जो है: 1) एकल उद्धरण चिह्नों के साथ शुरू और समाप्त होता है; 2) एकल उद्धरण चिह्न लगातार दो एकल उद्धरणों से बच जाते हैं। तो: इनपुट ['a' '] को आउटपुट [a] देना चाहिए। एक राज्य मशीन के साथ, लगातार एकल उद्धरण चिह्न दो राज्यों द्वारा नियंत्रित किए जाते हैं। ये दो राज्य इनपुट इतिहास को याद रखने के उद्देश्य से कार्य करते हैं जैसे कि प्रत्येक इनपुट चरित्र को केवल एक बार संसाधित किया जाता है, जैसा कि निम्नलिखित सचित्र है:

...
S1->'->S2
S1->*->S1, output *, * can be any other character 
S2->'->S1, output '
S2->*->END, end the current string

इसलिए, मेरी राय में, कुछ तुच्छ मामलों में नियमित अभिव्यक्ति धीमी हो सकती है, लेकिन आमतौर पर मैन्युअल रूप से तैयार की गई खोज एल्गोरिथ्म की तुलना में तेज़ होती है, इस तथ्य को देखते हुए कि अनुकूलन मानव द्वारा मज़बूती से नहीं किया जा सकता है।

(यहां तक ​​कि एक स्ट्रिंग को खोजने जैसे तुच्छ मामलों में, एक स्मार्ट इंजन राज्य के नक्शे में एकल पथ को पहचान सकता है और उस हिस्से को एक साधारण स्ट्रिंग तुलना में कम कर सकता है और प्रबंध राज्यों से बच सकता है।)

एक फ्रेमवर्क / लाइब्रेरी से एक विशेष इंजन धीमा हो सकता है क्योंकि इंजन अन्य चीजों का एक गुच्छा करता है जो एक प्रोग्रामर को आमतौर पर ज़रूरत नहीं होती है। उदाहरण: .NET में Regex वर्ग मैच, समूह और कैप्चर सहित वस्तुओं का एक समूह बनाता है।


2
मैं खुद भी इससे बेहतर नहीं बोल सकता था। केवल एक चीज मैं जोड़ूंगा: रेगुलर एक्सप्रेशंस भी आलसी प्रोग्रामर के लिए बना सकते हैं । उदाहरण में आपने aaaab|aaaac|aaaadबनाम aaaa[bcd]। यह स्पष्ट रूप से कहने योग्य है कि दोनों गणितीय रूप से समान हैं और एक ही DFA का उत्पादन करते हैं, इस प्रकार प्रोग्रामर को एक नियमित अभिव्यक्ति का प्रतिनिधित्व करने की अधिक स्वतंत्रता इस तरह से मिलती है जो समझ में आता है (यह नहीं कि यह सामान्य अभ्यास है, लेकिन ... y'know)। ..
रिवलॉक

धन्यवाद, यह वास्तव में ऑटोमेटा वर्ग के लिए धन्यवाद का अर्थ है जो मैंने लिया
lazeR

इस एक छोटी सी समस्या का एक उदाहरण है जहां regex है overkill ?: stackoverflow.com/questions/18955099/...
Menelaos Bakopoulos

17

नियमित अभिव्यक्तियाँ केवल तेज़ दिखती हैं क्योंकि आपके पास तेज़ कंप्यूटर हैं।

1980 में जब 1 MIPS एक तेज कंप्यूटर था, नियमित अभिव्यक्ति चिंता, चिंता और अनुसंधान का एक बड़ा क्षेत्र था क्योंकि वे धीमे और बदसूरत थे और गहन गणना करते थे। चतुर एल्गोरिथ्म विकास ने पीछा किया और मदद की - लेकिन इन दिनों सभी व्यावहारिक उद्देश्यों के लिए आप तेजी से मशीनों के चमत्कार को देख रहे हैं जो दरारों से टकरा रहे हैं।


2
यदि आप केवल एक ही शब्द की तलाश कर रहे हैं तो दोनों विधियाँ समान हैं (या regexp थोड़ा धीमा है)। लेकिन एक जटिल अभिव्यक्ति (और एक बड़े आकार का पाठ) को देखते हुए, नियमित अभिव्यक्ति संभवतः एक सरल खोज की तुलना में तेज़ होगी (यह मानते हुए कि आप साधारण खोज को सरलता से लिखते हैं (आप हमेशा एक जटिल खोज लिख सकते हैं जो जितनी तेज़ है)। अब मौसम यह महत्वपूर्ण है कि यह बहुत सामान्य सवाल है और आपको इसे मामले के आधार पर देखना होगा।
मार्टिन न्यू यॉर्क

3
-1। नियमित अभिव्यक्ति का सिद्धांत 50 के दशक का है और शाब्दिक विश्लेषणकर्ता (और विस्तार, संकलक) बनाने में सहायक था। वे बहुत ही कुशल राज्य मशीनें बनाते हैं जो (निश्चित रूप से) संभव राज्यों की सबसे कम संख्या का उपयोग करते हैं। परिणामी राज्य मशीनें आपके द्वारा लिखी जाने वाली चीज़ों की तुलना में बहुत तेज़ी से जटिल पैटर्न से मेल खा सकती हैं। वे तेज दिखते हैं क्योंकि वे तेज हैं।
रिवलॉक

मेरी बात थोड़ी याद आ गई होगी। वे "तेज" हो सकते हैं, लेकिन सभी रिश्तेदार हैं - अभी भी काम करने का एक गुच्छा है। कुछ अन्य उत्तर यहां भी पढ़े जाते हैं।
जल्दी_अगले

क्या यह उत्तर प्रश्न के लिए प्रासंगिक है? और 13 अपवोट्स कैसे?
सदानंद

7

आपको क्यों लगता है कि वे दस्तावेज़ की खोज करने की तुलना में तेज हैं?

कुछ ट्रिक्स हैं जो आप कर सकते हैं, जैसे। यदि आप A के साथ शुरू और B के साथ समाप्त होने वाले 10 पत्र शब्द की खोज कर रहे हैं, तो यदि आपको A और वर्ण 9 स्थितियां B पर मिलें तो आप कुछ को छोड़ सकते हैं। देखना नुथ-मॉरिस-प्रैट एल्गोरिथ्म


5

एक नियमित अभिव्यक्ति तेज क्या है?

असल में, वे नहीं हैं। इतना भी नहीं। यह सिर्फ इतना है कि वे हम में से अधिकांश के लिए नोटिस करने के लिए पर्याप्त धीमा नहीं कर रहे हैं। वापस 'पुराने धीमे दिनों में, यह अधिक ध्यान देने योग्य था।

वे भी हर काम के लिए सही उपकरण नहीं हैं - हथौड़ा


+1 कला के उस विशेष कार्य की याद दिलाने के लिए धन्यवाद ...
yannis

5

RegEx के तुलनात्मक रूप से आप कोड के लिए तेजी से लिख सकते हैं क्योंकि अधिकांश पुस्तकालय कई डेवलपर्स द्वारा कई वर्षों के खर्च करने का परिणाम हैं जो उन्हें हर संभव प्रदर्शन के अंतिम बिट को समाप्त करने के लिए अनुकूलित करते हैं। किसी एक व्यक्ति के लिए अपने स्वयं के खोज कोड में डुप्लिकेट करना मुश्किल है।


4
s / चीख़ / निचोड़ /?
Péter Török

4

आपका मूल आधार गलत है।

नियमित अभिव्यक्ति हमेशा एक सरल खोज से तेज नहीं होती है। यह सब संदर्भ पर निर्भर करता है। यह अभिव्यक्ति की जटिलता, खोजे जा रहे दस्तावेज़ की लंबाई और कारकों की एक पूरी मेजबानी पर निर्भर करता है।

क्या होता है कि नियमित अभिव्यक्ति को एक साधारण पार्सर (जो समय लगता है) में संकलित किया जाएगा। इस प्रकार, यदि दस्तावेज़ छोटा है, तो यह अतिरिक्त समय किसी भी लाभ से आगे निकल जाएगा। इसके अलावा, यदि अभिव्यक्ति सरल है, तो नियमित अभिव्यक्ति आपको कोई लाभ नहीं देगी।

यदि अभिव्यक्ति जटिल है और दस्तावेज़ काफी बड़ा है, तो आप कुछ लाभ प्राप्त कर सकते हैं। चाहे यह पर्याप्त रूप से नियमित अभिव्यक्ति पर विचार करने के लिए पर्याप्त महत्वपूर्ण हो, यह बहुत कुछ इस बात पर निर्भर करेगा कि आप खोज में कितना प्रयास करना चाहते हैं (नियमित अभिव्यक्तियों में कुछ अनुकूलन हो सकते हैं जो एक पुस्तकालय प्रदान कर सकता है जो आपने खुद नहीं सोचा होगा)।

मैं जो कहना चाह रहा हूं वह यह है कि कोई सामान्यीकृत, कंबल उत्तर नहीं है। यदि आपके पास एक विशिष्ट अभिव्यक्ति (और एक ज्ञात दस्तावेज़ आकार) है, तो आप कह सकते हैं कि एक हाँ / नहीं का जवाब है कि क्या अभिव्यक्ति एक सरल खोज (और क्यों) से तेज होगी।

नियमित अभिव्यक्तियों का वास्तविक लाभ यह है कि एक बार जब आप समझ जाते हैं कि उन्हें कैसे लिखना है, तो एक जटिल खोज को संक्षिप्त तरीके से व्यक्त करने की क्षमता। क्योंकि यह एक सामान्यीकृत रूप है, आप तब ऐसे उपकरण बना सकते हैं जो खोजों की अनुमति उस तरह से दें जो सामान्य स्थिति में उपयोगी हो; यह आम तौर पर कम से कम एक सरल खोज के रूप में तेजी से होता है (न्यूनतम आकार के दस्तावेजों पर, इससे छोटे दस्तावेजों पर यह तब भी कोई फर्क नहीं पड़ता है, भले ही यह धीमा हो, यह अभी भी काफी तेज है)।


1

यह प्रशंसनीय है कि कुछ उच्च-स्तरीय भाषाओं (शायद जावास्क्रिप्ट) में, निम्न-स्तरीय भाषा (शायद C) में कार्यान्वित एक regex लाइब्रेरी का उपयोग करके उच्च-स्तरीय भाषा में पार्सर तर्क लिखने से अधिक तेज़ होगा।

प्रशंसनीय - मुझे नहीं पता कि क्या वास्तव में कभी ऐसा होता है।


अच्छा है! यह कुछ ऐसा है जिसे मैंने भी माना है। लेकिन आज के प्रोसेसर अपने पूर्ववर्तियों की तुलना में तेजी से आगे बढ़ते हैं, मैं सुरक्षित रूप से कह सकता हूं यदि आप कुशलतापूर्वक कोड लिखते हैं, तो आप शायद ही कभी अंतर बताने में सक्षम होंगे। मैं वास्तव में पूरी तरह से पूरी नियमित अभिव्यक्ति पर नहीं हकीकत में तेजी से परिकल्पना कर रहा हूँ! ;-)
user3833732
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.