रेगेक्स गोल्फ के लिए टिप्स


43

भाषा-विशिष्ट गोल्फ टिप्स के लिए हमारे धागे के समान: नियमित अभिव्यक्तियों को छोटा करने के लिए सामान्य चालें क्या हैं?

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

हमेशा की तरह, कृपया प्रति उत्तर एक टिप (या बहुत बारीकी से संबंधित सुझावों का परिवार) से चिपके रहें, ताकि सबसे उपयोगी युक्तियां मतदान के माध्यम से शीर्ष पर पहुंच सकें।


प्रमुख स्व-प्रचार: रेगेक्स-उपयोग किस श्रेणी में आता है? codegolf.stackexchange.com/a/37685/8048
काइल स्ट्रैंड

@KyleStrand "नियमित अभिव्यक्ति बड़े गोल्फ कोड के भागों के रूप में उपयोग की जाती है।"
मार्टिन एंडर

जवाबों:


24

जब बचना नहीं है

ये नियम अधिकांश स्वादों पर लागू होते हैं, यदि सभी नहीं:

  • ] बेजोड़ होने पर भागने की जरूरत नहीं है।

  • {और }जब उन्हें पुनरावृत्ति का हिस्सा नहीं है, तो भागने की ज़रूरत नहीं है, उदाहरण के लिए शाब्दिक रूप से {a}मेल खाता {a}है। यहां तक ​​कि अगर आप कुछ पसंद करना चाहते हैं {2}, तो आपको केवल उनमें से एक से बचने की जरूरत है, जैसे {2\}

चरित्र वर्गों में:

  • ]जब एक चरित्र सेट में पहला चरित्र होता है, तो भागने की आवश्यकता नहीं होती है, जैसे कि []abc]किसी एक से मेल खाता है ]abc, या जब एक के बाद दूसरा चरित्र होता है ^, जैसे [^]]कुछ भी लेकिन मेल खाता है ]। (उल्लेखनीय अपवाद: ECMAScript फ्लेवर!)

  • [भागने की बिल्कुल जरूरत नहीं है। उपरोक्त टिप के साथ, इसका मतलब है कि आप दोनों कोष्ठक को बुरी तरह से काउंटर-सहज चरित्र वर्ग के साथ मिला सकते हैं [][]

  • ^जब एक चरित्र सेट में पहला चरित्र नहीं है, उदाहरण के लिए भागने की जरूरत नहीं है [ab^c]

  • -भागने की जरूरत नहीं है जब यह या तो पहले (दूसरे के बाद दूसरा ^) या चरित्र सेट में अंतिम चरित्र, जैसे [-abc], [^-abc]या [abc-]

  • चरित्र वर्ग के अंदर किसी अन्य पात्र को भागने की आवश्यकता नहीं है, भले ही वे चरित्र वर्ग के बाहर मेटा वर्ण हों (केवल \स्वयं को छोड़कर )।

इसके अलावा, कुछ स्वादों में ^और $शाब्दिक रूप से मेल खाते हैं जब वे क्रमशः रेगेक्स के शुरू या अंत में नहीं होते हैं।

(कुछ विवरणों को भरने के लिए @ मार्टिनबरनर को धन्यवाद)


कुछ लोग वास्तविक डॉट को चरित्र वर्ग में संलग्न करके बचना पसंद करते हैं, जहाँ उसे भागने की आवश्यकता नहीं होती है (जैसे। [.])। इसे सामान्य रूप से बचाना इस मामले में 1 बाइट बचाएगा\.
CS

ध्यान दें कि [जावा में बच जाना चाहिए। हालाँकि, ICU (Android और iOS में प्रयुक्त) या .NET के बारे में निश्चित नहीं है।
n --h'a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

18

ASCII तालिका में सभी मुद्रण योग्य वर्णों का मिलान करने के लिए एक सरल नियमित अभिव्यक्ति ।

[ -~]

1
शुद्ध awesomeness, एक मानक अमेरिकी कीबोर्ड से सभी चार्ट! नोट: मानक आस्की टेबल (विस्तारित रेंज 127-255 शामिल नहीं है
CS

मैं इसे अक्सर उपयोग करता हूं, लेकिन यह एक सामान्य "नियमित" चरित्र गायब है: TAB। और यह मानता है कि आप LC_ALL = "C" (या समान) का उपयोग कर रहे हैं क्योंकि कुछ अन्य स्थान विफल हो जाएंगे।
ओलिवियर दुलक

क्या ASCII तालिका में वर्णों की किसी भी सीमा को निर्दिष्ट करने के लिए हाइफ़न का उपयोग किया जा सकता है? Regex के सभी स्वादों के लिए वह काम करता है?
जोश विटही

14

अपने रेगेक्स जायके को जानें

ऐसे लोगों की एक आश्चर्यजनक मात्रा है जो सोचते हैं कि नियमित रूप से अभिव्यक्ति अनिवार्य रूप से भाषा अज्ञेय है। हालांकि, स्वाद के बीच वास्तव में काफी अंतर हैं, और विशेष रूप से कोड गोल्फ के लिए उनमें से कुछ को जानना अच्छा है, और उनकी दिलचस्प विशेषताएं हैं, इसलिए आप प्रत्येक कार्य के लिए सबसे अच्छा चुन सकते हैं। यहाँ कई महत्वपूर्ण स्वादों का अवलोकन है और जो उन्हें दूसरों से अलग करता है। (यह सूची वास्तव में पूरी नहीं हो सकती है, लेकिन मुझे बताएं कि क्या मैं वास्तव में कुछ याद कर रहा हूं।)

पर्ल और पीसीआरई

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

  • रिकर्सन / सबरूटीन्स । संभवतः गोल्फ के लिए सबसे महत्वपूर्ण विशेषता (जो केवल कुछ स्वादों में मौजूद है)।
  • सशर्त पैटर्न (?(group)yes|no)
  • समर्थन के साथ प्रतिस्थापन स्ट्रिंग में मामले की बदल \l, \u, \Lऔर \U
  • पीसीआरई लुकबाइंड्स में विकल्प की अनुमति देता है, जहां प्रत्येक विकल्प में एक अलग (लेकिन निश्चित) लंबाई हो सकती है। (अधिकांश स्वादों में, पर्ल सहित लुकहाइंड्स की कुल निश्चित लंबाई होनी चाहिए।)
  • \G पिछले मैच के अंत के लिए एक मैच लंगर करने के लिए।
  • \K मैच की शुरुआत को रीसेट करने के लिए
  • PCRE यूनिकोड के चरित्र गुणों और लिपियों दोनों का समर्थन करता है ।
  • \Q...\Eपात्रों के लंबे रन से बचने के लिए। उपयोगी जब आप एक स्ट्रिंग से मेल खाने की कोशिश कर रहे हैं जिसमें कई मेटा-वर्ण हैं।

नेट

यह शायद सबसे शक्तिशाली स्वाद है, जिसमें बहुत कम कमियां हैं।

गोल्फिंग के संदर्भ में एक महत्वपूर्ण कमी यह है कि यह कुछ अन्य स्वादों की तरह प्रभावशाली मात्राओं का समर्थन नहीं करता है। इसके बजाय .?+आपको लिखना होगा (?>.?)

जावा

  • एक बग के कारण (परिशिष्ट देखें) जावा सीमित प्रकार के चर-लंबाई वाले लुकबाइंड का समर्थन करता है: आप स्ट्रिंग की शुरुआत के लिए सभी तरह .*से देख सकते हैं जहां से आप अब एक लुकहेड शुरू कर सकते हैं, जैसे (?<=(?=lookahead).*)
  • वर्ण वर्गों के मिलन और अंतरंग का समर्थन करता है।
  • यूनिकोड के लिए सबसे व्यापक समर्थन है, "यूनिकोड लिपियों, ब्लॉकों, श्रेणियों और बाइनरी गुणों" के लिए चरित्र वर्गों के साथ ।
  • \Q...\E के रूप में पर्ल / पीसीआरई में।

माणिक

हाल के संस्करणों में, यह स्वाद पीसीआरई के समान शक्तिशाली है, जिसमें सबरूटीन कॉल के लिए समर्थन भी शामिल है। जावा की तरह, यह चरित्र वर्गों के संघ और चौराहे का भी समर्थन करता है। एक विशेष विशेषता हेक्स अंकों के लिए अंतर्निहित चरित्र वर्ग है: \h(और नकारात्मक \H)।

गोल्फ के लिए सबसे उपयोगी सुविधा हालांकि रूबी क्वांटिफायर को कैसे संभालती है। सबसे विशेष रूप से, यह कोष्ठक के बिना क्वांटिफायर घोंसले के लिए संभव है। .{5,7}+काम करता है और ऐसा ही करता है .{3}?। साथ ही, अधिकांश अन्य स्वादों के विपरीत, यदि एक क्वांटिफायर पर निचली बाउंड को 0छोड़ा जा सकता है, तो .{,5}इसके बराबर है .{0,5}

सबरूटीन्स के लिए, PCRE के सबरूटीन्स और रूबी के सबरूटीन के बीच प्रमुख अंतर यह है कि रूबी का सिंटैक्स एक बाइट लंबा (?n)बनाम है \g<n>, लेकिन रूबी के सबरूटीन का उपयोग कैप्चरिंग के लिए किया जा सकता है, जबकि PCRE एक सबरूटीन खत्म होने के बाद कैप्चर करता है।

अंत में, रूबी के पास अन्य सभी स्वादों की तुलना में लाइन से संबंधित संशोधकों के लिए अलग शब्दार्थ है। आमतौर पर mअन्य स्वादों में कहा जाने वाला संशोधक हमेशा रूबी में होता है। इसलिए ^और $हमेशा एक लाइन की शुरुआत और अंत का मिलान करें न कि केवल स्ट्रिंग की शुरुआत और अंत। यदि आप इस व्यवहार की जरूरत है यह आपको एक बाइट को बचा सकता है, लेकिन यह अगर तुम नहीं आप अतिरिक्त बाइट्स खर्च होंगे, क्योंकि आप प्रतिस्थापित करना होगा ^और $साथ \Aऔर \z, क्रमशः। इसके अलावा, आमतौर पर कहा जाता है कि संशोधक s(जो .मैच लाइनफीड बनाता है ) को mरूबी में बुलाया जाता है। यह बाइट काउंट को प्रभावित नहीं करता है, लेकिन भ्रम से बचने के लिए इसे ध्यान में रखा जाना चाहिए।

अजगर

पायथन में एक ठोस स्वाद है, लेकिन मैं किसी भी विशेष रूप से उपयोगी सुविधाओं से अवगत नहीं हूं जो आपको कहीं और नहीं मिलेगा।

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

ECMAScript

ECMAScript स्वाद बहुत सीमित है, और इसलिए शायद ही कभी गोल्फ के लिए बहुत उपयोगी है। केवल एक चीज जो इसके लिए जा रही है, वह है किसी भी चरित्र के साथ-साथ बिना शर्त खाली चरित्र वर्ग (हमेशा की तरह विपरीत ) के साथ मेल खाने के लिए उपेक्षित खाली चरित्र वर्ग । दुर्भाग्य से, स्वाद में कोई विशेषता नहीं है जो सामान्य समस्याओं के लिए उत्तरार्द्ध को उपयोगी बनाता है।[^][](?!)

लुआ

लुआ का अपना एक अनूठा स्वाद है, जो काफी सीमित है (जैसे कि आप समूहों को निर्धारित नहीं कर सकते हैं) लेकिन यह उपयोगी और दिलचस्प सुविधाओं के साथ आता है।

  • इसमें अंतर्निर्मित चरित्र वर्गों के लिए बड़ी संख्या में शॉर्टहैंड हैं , जिनमें विराम चिह्न, ऊपरी / निचले मामले के वर्ण और हेक्स अंक शामिल हैं।
  • इसके साथ %bसंतुलित तारों का मिलान करने के लिए एक बहुत ही कॉम्पैक्ट सिंटैक्स का समर्थन करता है। उदाहरण के लिए %b()एक मैच (और फिर एक मिलान तक सब कुछ )(सही ढंग से आंतरिक मिलान जोड़े को छोड़ देना)। (और )यहां कोई भी दो वर्ण हो सकते हैं।

बढ़ावा

बूस्ट का रेगेक्स स्वाद अनिवार्य रूप से पर्ल का है। हालांकि, इसमें रेगेक्स प्रतिस्थापन के लिए कुछ अच्छी नई विशेषताएं हैं, जिनमें केस परिवर्तन और सशर्तियां शामिल हैं । उत्तरार्द्ध बूस्ट के लिए अद्वितीय है जहाँ तक मुझे पता है।


ध्यान दें कि लुक-बैक में आगे की ओर लुक-बाउंड में सीमा के माध्यम से पंच होगा। जावा और पीसीआरई में परीक्षण किया गया।
n --h'a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

के .?+बराबर नहीं है .*?
कैलकुलेटर

@CalculatorFeline पूर्व में एक संपूरक 0-or-1 क्वांटिफायर है (जायके में जो समर्थन मात्रात्मक मात्रा का समर्थन करता है), बाद वाला एक 0 या अधिक क्वांटिफायर है।
मार्टिन एंडर

@ कलालुफ़रलाइन आह मुझे भ्रम की समझ है। एक टाइपो था।
मार्टिन एंडर

13

अपने चरित्र वर्गों को जानें

अधिकांश रेगेक्स फ्लेवर्स में चरित्र वर्ग पूर्वनिर्धारित हैं। उदाहरण के लिए, \dएक दशमलव अंक से मेल खाता है, जो तीन बाइट से छोटा है [0-9]। हां, वे थोड़े अलग \dहो सकते हैं क्योंकि वे यूनिकोड अंकों के साथ-साथ कुछ स्वादों में भी मेल खा सकते हैं, लेकिन ज्यादातर चुनौतियों के लिए इससे कोई फर्क नहीं पड़ेगा।

यहाँ कुछ चरित्र वर्ग पाए जाते हैं जो अधिकांश रेगीक्स फ्लेवर में पाए जाते हैं:

\d      Match a decimal digit character
\s      Match a whitespace character
\w      Match a word character (typically [a-zA-Z0-9_])

इसके अलावा, हमारे पास भी है:

\D \S \W

जो ऊपर के नकारात्मक संस्करण हैं।

किसी भी अतिरिक्त चरित्र वर्गों के लिए अपने स्वाद की जांच करना सुनिश्चित करें। उदाहरण के लिए, पीसीआरई में \Rन्यूलाइन्स और लुआ के लिए भी लोअरकेस और अपरकेस वर्ण जैसी कक्षाएं हैं।

(इन्हें इंगित करने के लिए @ HamZa और @ MartinBüttner को धन्यवाद)


3
\RPCRE में newlines के लिए।
हमजा

12

गैर-कैप्चरिंग समूहों के साथ परेशान न करें (जब तक ...)

यह टिप कम से कम सभी लोकप्रिय पर्ल से प्रेरित स्वादों पर लागू होती है।

यह स्पष्ट हो सकता है, लेकिन (जब गोल्फ नहीं) यह गैर-कैप्चरिंग समूहों का उपयोग करने के लिए (?:...)जब भी संभव हो अच्छा अभ्यास है। ?:हालांकि गोल्फिंग करते समय ये दो अतिरिक्त वर्ण बेकार हैं, इसलिए बस कैप्चरिंग समूहों का उपयोग करें, भले ही आप उन्हें पीछे हटाना न हों।

हालांकि एक (दुर्लभ) अपवाद है: यदि आप 10कम से कम 3 बार समूह को पीछे हटाना चाहते हैं, तो आप वास्तव में पहले के समूह को गैर-कैप्चरिंग समूह में बदलकर बाइट्स को बचा सकते हैं, जैसे कि वे सभी \10एस बन जाते हैं \9। (इसी तरह के ट्रिक्स लागू होते हैं, यदि आप 11कम से कम 5 बार समूह का उपयोग करते हैं और इसी तरह।)


जब 10 को 3 की आवश्यकता होती है तो 11 को इसके लायक होने की आवश्यकता क्यों होती है?
निक हार्टले

1
@QPaysTaxes के $9बजाय $10या $11एक बार उपयोग करने में सक्षम होने के नाते एक बाइट बचाता है। एक को चालू $10करने की $9आवश्यकता है ?:, जो दो बाइट्स है, इसलिए आपको $10कुछ बचाने के लिए तीन एस की आवश्यकता होगी । टर्निंग $11में $9दो ?:एस की आवश्यकता होती है जो चार बाइट्स है, इसलिए आपको $11कुछ (या पांच $10और $11संयुक्त) को बचाने के लिए पांच एस की आवश्यकता होगी ।
मार्टिन एंडर

10

पैटर्न पुन: उपयोग के लिए पुनरावृत्ति

मुट्ठी भर जायके पुनरावर्तन का समर्थन करते हैं ( मेरे ज्ञान , पर्ल, पीसीआरई और रूबी के लिए)। जब आप पुनरावर्ती समस्याओं को हल करने का प्रयास नहीं कर रहे हैं, तब भी यह सुविधा अधिक जटिल पैटर्न में बहुत सारे बाइट्स बचा सकती है । उस समूह के अंदर किसी अन्य (नामित या क्रमांकित) समूह को कॉल करने की आवश्यकता नहीं है। यदि आपके पास एक निश्चित पैटर्न है जो आपके रेगेक्स में कई बार दिखाई देता है, तो इसे समूह बनाएं और इसे उस समूह के बाहर देखें। यह सामान्य प्रोग्रामिंग भाषाओं में सबरूटिन कॉल से अलग नहीं है। इसलिए इसके बजाय

...someComplexPatternHere...someComplexPatternHere...someComplexPatternHere... 

पर्ल / पीसीआरई में आप यह कर सकते हैं:

...(someComplexPatternHere)...(?1)...(?1)...

या रूबी में:

...(someComplexPatternHere)...\g<1>...\g<1>...

बशर्ते वह पहला समूह हो (बेशक, आप पुनरावर्ती कॉल में किसी भी संख्या का उपयोग कर सकते हैं)।

ध्यान दें कि यह बैकरेंस ( ) के समान नहीं है \1। Backreferences सटीक उसी स्ट्रिंग से मेल खाते हैं जो पिछली बार समूह से मेल खाता था। ये सबरूटीन कॉल वास्तव में फिर से पैटर्न का मूल्यांकन करते हैं। someComplexPatternHereएक लंबा चरित्र वर्ग लेने के लिए एक उदाहरण के रूप में :

a[0_B!$]b[0_B!$]c[0_B!$]d

यह कुछ इस तरह मैच होगा

aBb0c!d

ध्यान दें कि व्यवहार को संरक्षित करते समय आप यहाँ बैकरेफ़रेंस का उपयोग नहीं कर सकते। एक backreference ऊपर स्ट्रिंग पर असफल है, क्योंकि होगा Bऔर 0और !ही नहीं हैं। हालांकि, सबरूटीन कॉल के साथ, पैटर्न वास्तव में पुनर्मूल्यांकित होता है। उपरोक्त पैटर्न पूरी तरह से समकक्ष है

a([0_B!$])b(?1)c(?1)d

सबरूटीन कॉल में कैप्चर करना

पर्ल और पीसीआरई के लिए सावधानी का एक नोट: यदि 1उपरोक्त उदाहरणों में समूह में आगे समूह शामिल हैं, तो सबरूटीन कॉल को उनके कैप्चर याद नहीं होंगे। इस उदाहरण पर विचार करें:

(\w(\d):)\2 (?1)\2 (?1)\2

यह मेल नहीं खाएगा

x1:1 y2:2 z3:3

क्योंकि सबरटीन कॉल लौटने के बाद, समूह 2का नया कब्जा छोड़ दिया जाता है। इसके बजाय, यह पैटर्न इस स्ट्रिंग से मेल खाएगा:

x1:1 y2:1 z3:1

यह रूबी, जहां सबरूटीन कॉल से अलग है ऐसा इसलिए बराबर रूबी regex, उनके कैप्चर बनाए रखने के (\w(\d):)\2 \g<1>\2 \g<1>\2ऊपर के उदाहरण के पहले से मेल खाएगा।


आप \1जावास्क्रिप्ट के लिए उपयोग कर सकते हैं । और PHP भी (मुझे लगता है)।
इस्माइल मिगुएल

5
@IsmaelMiguel यह एक पश्चगामी नहीं है। यह वास्तव में पैटर्न का फिर से मूल्यांकन करता है। उदाहरण के लिए (..)\1मेल खाएंगे ababलेकिन पर असफल abbaजबकि (..)(?1)उत्तरार्द्ध से मेल खाएगी। यह वास्तव में इस अर्थ में एक सबरूटीन कॉल है कि अभिव्यक्ति को फिर से लागू किया जाता है, इसके बजाय शाब्दिक रूप से मेल खाते हैं जो पिछली बार मेल खाते थे।
मार्टिन एंडर

वाह, मुझे पता नहीं था! कुछ नया हर रोज सीखना
इस्माइल मिगुएल

में .NET (या इस सुविधा के बिना अन्य जायके):(?=a.b.c)(.[0_B!$]){3}d
jimmy23013

@ user23013 जो इस विशेष उदाहरण के लिए बहुत विशिष्ट लगता है। मुझे यकीन नहीं है कि यह लागू हो सकता है अगर मैं विभिन्न लुकरॉइड्स में एक निश्चित उपपट्ट का पुन: उपयोग करता हूं।
मार्टिन एंडर

9

जिससे एक मैच फेल हो गया

कम्प्यूटेशनल समस्याओं को हल करने या अत्यधिक गैर-नियमित भाषाओं से मेल खाने के लिए regex का उपयोग करते समय, पैटर्न की एक शाखा बनाने के लिए कभी-कभी यह आवश्यक होता है कि आप स्ट्रिंग में कहां हैं। भोली दृष्टिकोण एक खाली नकारात्मक रूप का उपयोग करने के लिए है:

(?!)

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

!

या कोई अन्य गैर-अंक, गैर-मेटा चरित्र विफलता का कारण बनता है।

यहां तक ​​कि अगर आपके इनपुट में संभावित रूप से कोई भी सबस्ट्रिंग हो सकती है, तो इससे छोटे तरीके हैं (?!)। कोई भी स्वाद जो एंकर को अंत के विपरीत एक पैटर्न के भीतर प्रकट करने की अनुमति देता है, निम्नलिखित में से किसी भी 2-चरित्र समाधान का उपयोग कर सकता है:

a^
$a

हालांकि ध्यान दें कि कुछ जायके का इलाज करेंगे ^और $इन पदों पर शाब्दिक पात्रों के रूप में, क्योंकि वे स्पष्ट रूप से एंकर के रूप में समझ में नहीं आते हैं।

ECMAScript स्वाद में, बल्कि सुरुचिपूर्ण 2-चरित्र समाधान भी है

[]

यह एक खाली चरित्र वर्ग है, जो यह सुनिश्चित करने की कोशिश करता है कि अगला वर्ण कक्षा में से एक है - लेकिन कक्षा में कोई वर्ण नहीं है, इसलिए यह हमेशा विफल रहता है। ध्यान दें कि यह किसी भी अन्य स्वाद में काम नहीं करेगा, क्योंकि चरित्र वर्ग आमतौर पर खाली नहीं हो सकते।


8

आप का अनुकूलन करें

जब भी आपके RegEx में 3 या अधिक विकल्प हों:

/aliceblue|antiquewhite|aquamarine|azure/

यह देखने के लिए जांचें कि क्या कोई सामान्य शुरुआत है:

/a(liceblue|ntiquewhite|quamarine|zure)/

और शायद एक सामान्य अंत भी?

/a(liceblu|ntiquewhit|quamarin|zur)e/

नोट: 3 सिर्फ शुरुआत है और एक ही लंबाई के लिए खाता होगा, 4+ से फर्क पड़ेगा


लेकिन क्या होगा अगर उन सभी में एक सामान्य उपसर्ग न हो? (व्हॉट्सएप केवल स्पष्टता के लिए जोड़ा गया)

/aliceblue|antiquewhite|aqua|aquamarine|azure
|beige|bisque|black|blanchedalmond|blue|blueviolet|brown|burlywood
|cadetblue|chartreuse|chocolate|coral|cornflowerblue|cornsilk|crimson|cyan/

समूह उन्हें, जब तक 3+ नियम समझ में आता है:

/a(liceblue|ntiquewhite|qua|quamarine|zure)
|b(eige|isque|lack|lanchedalmond|lue|lueviolet|rown|urlywood)
|c(adetblue|hartreuse|hocolate|oral|ornflowerblue|ornsilk|rimson|yan)/

या यहां तक ​​कि सामान्यीकरण करें यदि एन्ट्रापी आपके usecase को संतुष्ट करता है:

/\w(liceblue|ntiquewhite|qua|quamarine|zure
|eige|isque|lack|lanchedalmond|lue|lueviolet|rown|urlywood
|adetblue|hartreuse|hocolate|oral|ornflowerblue|ornsilk|rimson|yan)/

^ इस मामले में हमें यकीन है कि हमें कोई भी clueया नहीं मिला हैcrown slack Ryan

यह "कुछ परीक्षणों के अनुसार" भी प्रदर्शन में सुधार करता है, क्योंकि यह शुरू करने के लिए एक लंगर प्रदान करता है ।


1
यदि सामान्य शुरुआत या अंत एक चरित्र से अधिक लंबा है, तो भी दो को समूहीकृत करने से फर्क पड़ सकता है। जैसे aqua|aquamarineaqua(|marine)या aqua(marine)?
Palo Ebermann

6

यह एक काफी सरल है, लेकिन इसके लायक है:

आप अपने आप को मिल जाए चरित्र वर्ग दोहरा [a-zA-Z]आप शायद अभी उपयोग कर सकते हैं [a-z]और संलग्न i(केस मैं nsensitive संशोधक) अपने रेगुलर एक्सप्रेशन से करने के लिए।

उदाहरण के लिए, रूबी में, निम्नलिखित दो रीजैक्स समतुल्य हैं:

/[a-zA-Z]+\d{3}[a-zA-Z]+/
/[a-z]+\d{3}[a-z]/i - 7 बाइट्स छोटी

उस मामले के लिए, अन्य संशोधक आपकी कुल लंबाई को छोटा कर सकते हैं। ऐसा करने के बजाय:

/(.|\n)/

जो किसी भी पात्र से मेल खाता है (क्योंकि डॉट न्यूलाइन से मेल नहीं खाता है), एस इंगल-लाइन संशोधक का उपयोग करता है s, जो डॉट मैच को नया बनाता है।

/./s - 3 बाइट्स छोटी


रूबी में, रेगेक्स के लिए एक टन में निर्मित चरित्र वर्ग हैं। इस पृष्ठ को देखें और "वर्ण गुण" खोजें।
एक महान उदाहरण "मुद्रा प्रतीक" है। विकिपीडिया के अनुसार संभव मुद्रा प्रतीकों का एक टन है, और उन्हें एक चरित्र वर्ग में रखना बहुत महंगा होगा ( [$฿¢₡Ð₫€.....]) जबकि आप उनमें से किसी भी 6 बाइट्स में मेल कर सकते हैं:\p{Sc}


1
जावास्क्रिप्ट को छोड़कर, जहां sसंशोधक समर्थित नहीं है। :( लेकिन वहाँ आप जावास्क्रिप्ट के स्वामित्व का उपयोग कर सकते /[^]/चाल।
manatwork

ध्यान दें कि (.|\n)कुछ स्वादों में भी काम नहीं करता है, क्योंकि .अक्सर अन्य प्रकार के लाइन विभाजकों से मेल नहीं खाता है। हालांकि, ऐसा करने के लिए प्रथागत तरीका (बिना s) है [\s\S]जो कि उसी बाइट के रूप में है (.|\n)
मार्टिन एंडर

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

@manatwork किया (और एक संबंधित गैर-ईएस विशिष्ट चाल के रूप में अच्छी तरह से जोड़ा)
मार्टिन एंडर

6

एक सरल भाषा पार्सर

आप एक आरई जैसे एक बहुत ही साधारण पार्सर का निर्माण कर सकते हैं \d+|\w+|".*?"|\n|\S। आपके द्वारा मिलान किए जाने वाले टोकन को RE 'या' वर्ण से अलग किया जाता है।

जब भी आरई इंजन पाठ में वर्तमान स्थिति में मिलान करने की कोशिश करता है, तो यह पहले पैटर्न की कोशिश करेगा, फिर दूसरा, आदि। यदि यह विफल रहता है (उदाहरण के लिए यहां एक अंतरिक्ष चरित्र पर), तो यह आगे बढ़ता है और फिर से मैचों की कोशिश करता है। । आदेश महत्वपूर्ण है। यदि हमने \Sपद से पहले पद रखा है \d+, तो \Sपहले किसी भी गैर-अंतरिक्ष चरित्र पर मिलान करेगा जो हमारे पार्सर को तोड़ देगा।

".*?"इसलिए हम केवल एक समय में एक स्ट्रिंग से मेल स्ट्रिंग मिलान एक गैर लालची संशोधक का उपयोग करता है। यदि आपके आरई में गैर-लालची कार्य नहीं हैं, तो आप उपयोग कर सकते हैं "[^"]*"जो समकक्ष है।

पायथन उदाहरण:

text = 'd="dogfinder"\nx=sum(ord(c)*872 for c in "fish"+d[3:])'
pat = r'\d+|\w+|".*?"|\n|\S'
print re.findall(pat, text)

['d', '=', '"dogfinder"', '\n', 'x', '=', 'sum', '(', 'ord', '(', 'c', ')',
    '*', '872', 'for', 'c', 'in', '"fish"', '+', 'd', '[', '3', ':', ']', ')']

गोल्फ का अजगर उदाहरण:

# assume we have language text in A, and a token processing function P
map(P,findall(r'\d+|\w+|".*?"|\n|\S',A))

आप जिस भाषा से मेल खाना चाहते हैं, उसके लिए आप उनके पैटर्न और उनके क्रम को समायोजित कर सकते हैं। यह तकनीक JSON, मूल HTML और संख्यात्मक अभिव्यक्तियों के लिए अच्छी तरह से काम करती है। इसका उपयोग पायथन 2 के साथ कई बार सफलतापूर्वक किया गया है, लेकिन अन्य वातावरणों में काम करने के लिए पर्याप्त सामान्य होना चाहिए।


6

\K इसके बजाय सकारात्मक दिखावे की

PCRE और पर्ल भागने के क्रम का समर्थन करते हैं \K, जो मैच की शुरुआत को रीसेट करता है। है कि ab\Kcdको रोकने के लिए अपने इनपुट स्ट्रिंग की आवश्यकता होगी abcd, लेकिन रिपोर्ट मैच केवल हो जाएगा cd

यदि आप अपने पैटर्न की शुरुआत में एक सकारात्मक खोजबीन का उपयोग कर रहे हैं (जो संभवतः सबसे संभावित स्थान है), तो ज्यादातर मामलों में, आप \Kइसके बजाय उपयोग कर सकते हैं और 3 बाइट्स बचा सकते हैं :

(?<=abc)def
abc\Kdef

यह अधिकांश उद्देश्यों के लिए बराबर है, लेकिन पूरी तरह से नहीं। मतभेद उनके साथ फायदे और नुकसान दोनों लाते हैं:

  • अपसाइड: पीसीआरई और पर्ल मनमानी-लंबाई वाली लुकबाइंड का समर्थन नहीं करते हैं (केवल .NET करता है)। यानी आप ऐसा कुछ नहीं कर सकते (?<=ab*)। लेकिन \Kआप इसके साथ किसी भी तरह का पैटर्न सामने रख सकते हैं! तो ab*\Kकाम करता है। यह वास्तव में इस तकनीक को उन मामलों में बहुत अधिक शक्तिशाली बनाता है जहां यह लागू है।
  • अपसाइड: लुकरॉइड्स पीछे नहीं हटते हैं। यह प्रासंगिक है यदि आप बाद में बैकरेस्ट के लिए लुकआउट में कुछ कैप्चर करना चाहते हैं, लेकिन कई संभावित कैप्चर हैं जो सभी वैध मैचों की ओर ले जाते हैं। इस मामले में, रेगेक्स इंजन केवल उन संभावनाओं में से एक का प्रयास करेगा। जब \Kरेगेक्स के उस हिस्से का उपयोग किया जा रहा है, तो बाकी सब चीजों की तरह पीछे किया जा रहा है।
  • नकारात्मक पक्ष: जैसा कि आप शायद जानते हैं, रेगेक्स के कई मैच ओवरलैप नहीं कर सकते हैं। इस सीमा के आसपास आंशिक रूप से काम करने के लिए अक्सर लुकरॉइड्स का उपयोग किया जाता है, क्योंकि लुकहेड स्ट्रिंग के एक हिस्से को मान्य कर सकता है जो पहले से ही एक मैच से पहले खा गया था। तो अगर आप सभी पात्रों कि मिलान करना चाहते थे पीछा ab आप उपयोग कर सकते हैं (?<=ab).। इनपुट दिया

    ababc
    

    यह दूसरी aऔर मैच होगा c। इसके साथ पुन: पेश नहीं किया जा सकता है \K। यदि आप उपयोग करते हैं ab\K., तो आपको केवल पहला मैच मिलेगा, क्योंकि अब वह abलुक में नहीं है।


यदि एक पैटर्न \Kसकारात्मक दावे के भीतर भागने के अनुक्रम का उपयोग करता है , तो एक सफल मैच की रिपोर्ट की गई शुरुआत मैच के अंत से अधिक हो सकती है।
hwnd

@hwnd मेरे मुद्दा यह है कि दिए गए है ababc, वहाँ कोई रास्ता नहीं है दोनों दूसरे मैच के लिए है aऔर cसाथ \K। आपको केवल एक मैच मिलेगा।
मार्टिन एंडर

आप सही हैं, सुविधा के साथ नहीं। आपके साथ लंगर करना होगा\G
hwnd

@hwnd आह मैं अब आपकी बात देखता हूं। लेकिन मुझे लगता है कि उस बिंदु पर (एक गोल्फ दृष्टिकोण से) आप एक नकारात्मक खोज के साथ बेहतर हैं, क्योंकि आप वास्तव में इसे वैसे भी आवश्यकता हो सकती है क्योंकि आप यह सुनिश्चित नहीं कर सकते कि .पिछले मैच से वास्तव में एक था a
मार्टिन एंडर

1
दिलचस्प है \ K =) का उपयोग
hwnd

5

किसी भी पात्र से मेल खाना

ECMAScript फ्लेवर में उन sसंशोधकों की कमी होती है जो .किसी भी वर्ण (newlines सहित) से मेल खाते हैं। इसका मतलब है कि पूरी तरह से मनमाने चरित्रों के मिलान के लिए कोई एकल-वर्ण समाधान नहीं है। अन्य स्वादों में मानक समाधान (जब कोई sकिसी कारण से उपयोग नहीं करना चाहता ) है [\s\S]। हालाँकि, ECMAScript एकमात्र स्वाद (मेरी जानकारी के लिए) है जो खाली वर्ण वर्गों का समर्थन करता है, और इसलिए इसका बहुत कम विकल्प है [^]:। यह एक नकारात्मक खाली चरित्र वर्ग है - अर्थात, यह किसी भी चरित्र से मेल खाता है।

अन्य स्वादों के लिए भी, हम इस तकनीक से सीख सकते हैं: यदि हम उपयोग नहीं करना चाहते हैं s(उदाहरण के लिए, क्योंकि हमें अभी भी .अन्य स्थानों पर सामान्य अर्थ की आवश्यकता है ), तो फिर भी न्यूलाइन और प्रिंट करने योग्य दोनों वर्णों का मिलान करने का एक छोटा तरीका हो सकता है, बशर्ते कुछ ऐसा चरित्र हो जो हमें पता हो कि इनपुट में दिखाई नहीं देता है। कहते हैं, हम नई संख्याओं द्वारा सीमांकित संख्या को संसाधित कर रहे हैं। तब हम किसी भी पात्र के साथ मेल कर सकते हैं [^!], क्योंकि हम जानते हैं कि !वह कभी भी स्ट्रिंग का हिस्सा नहीं होगा। यह भोले पर दो बाइट्स बचाता है [\s\S]या [\d\n]


4
पर्ल में, \Nवास्तव .में /sमोड के बाहर का मतलब है, सिवाय इसके कि यह किसी मोड से प्रभावित न हो।
कोनराड बोरोस्की

4

परमाणु समूहों और अधिकारी मात्रात्मक का उपयोग करें

मैं परमाणु समूहों (पाया (?>...)) और अधिकार परिमाणकों ( ?+, *+, ++, {m,n}+) कभी कभी गोल्फ के लिए बहुत उपयोगी। यह एक तार से मेल खाता है और बाद में पीछे हटना बंद कर देता है। तो यह केवल पहले परिपक्व होने वाले स्ट्रिंग से मेल खाएगा जो रेगेक्स इंजन द्वारा पाया जाता है।

उदाहरण के लिए: aशुरुआत में विषम संख्या के साथ एक तार से मेल खाने के लिए , जिसका अनुसरण अधिक नहीं है a, आप इसका उपयोग कर सकते हैं:

^(aa)*+a
^(?>(aa)*)a

यह आपको .*स्वतंत्र रूप से चीजों का उपयोग करने की अनुमति देता है , और अगर एक स्पष्ट मैच है, तो बहुत अधिक या बहुत कम वर्णों के मिलान की एक और संभावना नहीं होगी, जो आपके पैटर्न को तोड़ सकती है।

.NET रेगेक्स में (जिसके पास मात्रात्मक मात्रात्मक नहीं है), आप इसका उपयोग पॉप समूह 1 में 3 की सबसे बड़ी बहु (अधिकतम 30 के साथ) बार (बहुत अच्छी तरह से गोल्फ नहीं) कर सकते हैं:

(?>((?<-1>){3}|){10})


4

एक उपप्रकार के बाद एक कैप्चर किए गए समूह को भूल जाओ (PCRE)

इस regex के लिए:

^((a)(?=\2))(?!\2)

यदि आप समूह 1 के बाद \ 2 को खाली करना चाहते हैं, तो आप पुनरावृत्ति का उपयोग कर सकते हैं:

^((a)(?=\2)){0}(?1)(?!\2)

यह मैच होगा aaजबकि पिछले एक नहीं होगा। कभी-कभी आप भी उपयोग कर सकते हैं ??या यहां तक ​​कि ?के स्थान पर भी {0}

यह उपयोगी हो सकता है यदि आपने पुनरावर्ती का उपयोग किया है, और आपके रेक्सक्स में विभिन्न स्थानों में कुछ बैकरेफेरेंस या सशर्त समूह दिखाई दिए।

यह भी ध्यान दें कि परमाणु समूहों को पीसीआरई में पुनरावृत्ति के लिए ग्रहण किया जाता है। तो यह एक अक्षर से मेल नहीं खाएगा a:

^(a?){0}(?1)a

मैंने इसे अभी तक अन्य स्वादों में नहीं आज़माया।

लुकहेड्स के लिए, आप इस उद्देश्य के लिए दोहरे नकारात्मक का उपयोग कर सकते हैं:

^(?!(?!(a)(?=\1))).(?!\1)

4

वैकल्पिक अभिव्यक्ति

यह याद रखना कभी-कभी उपयोगी होता है

(abc)?

है ज्यादातर के रूप में ही

(abc|)

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

((abc)?)

संस्करण का उपयोग |तब भी उपयोगी होता है जब आप अभिव्यक्ति को समूह के किसी और रूप में लपेटना चाहते हैं और कैप्चरिंग की परवाह नहीं करते हैं:

(?=(abc)?)
(?=abc|)

(?>(abc)?)
(?>abc|)

अंत में, इस ट्रिक को असहमति के लिए भी लागू किया जा सकता है ?जहां यह अपने कच्चे रूप में भी एक बाइट बचाता है (और परिणामस्वरूप 3 बाइट्स जब समूहों के अन्य रूपों के साथ संयुक्त होता है):

(abc)??
(|abc)

1

एकाधिक लुकहैड्स जो हमेशा मेल खाते हैं (.NET)

यदि आपके पास 3 या अधिक लुकहेड कंस्ट्रक्शन हैं जो हमेशा मैच करते हैं (सबएक्सप्रेस को कैप्चर करने के लिए), या लुकहैड पर एक क्वांटिफायर होता है जिसके बाद कुछ और होता है, इसलिए उन्हें आवश्यक रूप से कैप्चर किए गए समूह में नहीं होना चाहिए:

(?=a)(?=b)(?=c)
((?=a)b){...}

ये छोटे हैं:

(?(?(?(a)b)c))
(?(a)b){...}

जहां aएक कब्जा समूह का नाम नहीं होना चाहिए। आप कोष्ठक की एक और जोड़ी को जोड़ने के बिना और |में सामान्य बात का उपयोग करने के लिए उपयोग नहीं कर सकते ।bc

दुर्भाग्य से, सशर्त समूहों में संतुलन कमजोर लग रहा था, जिससे यह कई मामलों में बेकार हो गया।

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