अपनी शक्ति खोए बिना पढ़ने योग्य नियमित भाव?


77

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

एक साधारण मामले के लिए परिणाम कुछ इस तरह हो सकता है, जैसे कि जावा रेगेक्स:

Pattern re = Pattern.compile(
  "^\\s*(?:(?:([\\d]+)\\s*:\\s*)?(?:([\\d]+)\\s*:\\s*))?([\\d]+)(?:\\s*[.,]\\s*([0-9]+))?\\s*$"
);

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

हालांकि, चीजों को और अधिक जटिल पाने के लिए एक regexp सही मायने में बनने के लिए बात है, और यहां तक कि मेहनती प्रलेखन (जो सबके साथ ही लिखना-की जरूरत नहीं है निश्चित रूप से सभी जटिल regexps वे लिखते हैं ... के लिए करता है), regexps को संशोधित करने के लिए एक हो जाता है चुनौतीपूर्ण कार्य। यह एक बहुत ही खतरनाक काम भी हो सकता है, अगर regexp को सावधानीपूर्वक जांच की गई इकाई नहीं है (लेकिन निश्चित रूप से सभी के पास अपने सभी जटिल regexps के लिए व्यापक इकाई परीक्षण हैं, दोनों सकारात्मक और नकारात्मक ...)।

तो, लंबी कहानी छोटी है, क्या उनकी शक्ति को खोए बिना नियमित अभिव्यक्ति के लिए एक लिखित-पढ़ा समाधान / विकल्प है? एक वैकल्पिक दृष्टिकोण के साथ उपरोक्त regexp कैसा दिखेगा? कोई भी भाषा ठीक है, हालांकि एक बहु-भाषा समाधान सबसे अच्छा होगा, डिग्री regexps बहु-भाषा है।


और फिर, पहले वाला रेग्जैक्स यह क्या करता है: प्रारूप में संख्याओं की एक स्ट्रिंग को पार्स करें 1:2:3.4, प्रत्येक संख्या को कैप्चर करना, जहां रिक्त स्थान की अनुमति है और केवल 3आवश्यक है।


2
SO पर संबंधित बात: stackoverflow.com/a/143636/674039
wim

24
यदि आप जानते हैं कि वे क्या कैप्चर करने वाले हैं, तो रीडिंग / एडिटिंग रेक्सेक्स वास्तव में मामूली है। आपने "टिप्पणियों" नामक अधिकांश भाषाओं की शायद ही कभी इस्तेमाल की जाने वाली विशेषता के बारे में सुना होगा। यदि आप एक जटिल रेगेक्स के ऊपर एक नहीं डालते हैं, तो यह बताते हुए कि यह आपको बाद में कीमत का भुगतान करेगा। इसके अलावा, कोड की समीक्षा करें।
191

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

3
समस्या का एक हिस्सा रेगेक्स भाषा ही है, और इसके डिजाइन में खराब ऐतिहासिक विकल्प जो सामान की तरह खींचे जाते हैं। एक समझदार भाषा में, कोष्ठक को आकार देने के लिए समूहबद्ध कोष्ठक शुद्ध रूप से एक युक्तिसंगत उपकरण होता है। लेकिन रीजेक्स की नकल में यूनिक्स में वापस जाने के लिए उनके पास शब्दार्थ है: उपप्रकार के मैचों के लिए बाध्यकारी रजिस्टर। तो फिर आपको शुद्ध समूहीकरण प्राप्त करने के लिए कुछ और जटिल, बदसूरत कोष्ठक की आवश्यकता है!
काज

2
वास्तव में व्यावहारिक उत्तर नहीं है, लेकिन यह उल्लेख करना उपयोगी हो सकता है कि नियमित अभिव्यक्ति की शक्ति ठीक एक परिमित ऑटोमेटन के समान है। यही है, रेगीक्स परिमित ऑटोमैटनों द्वारा मान्य और पार्स किए गए तारों के एक ही वर्ग को मान्य / पार्स कर सकते हैं। इसलिए, रेगेक्स का एक मानव पठनीय प्रतिनिधित्व संभवतः एक ग्राफ बनाने में सक्षम होना चाहिए, और मुझे विश्वास है कि अधिकांश पाठ-आधारित भाषा वास्तव में इस पर खराब हैं; इसलिए हम ऐसी चीजों के लिए विजुअल टूल्स का इस्तेमाल करते हैं। कुछ प्रेरणा पाने के लिए hackingoff.com/compilers/ अनियमित-expression- to- nfa-dfa पर एक नज़र डालें ।
डेमिक्स 911

जवाबों:


80

कई लोगों ने छोटे भागों से रचना का उल्लेख किया है, लेकिन किसी ने अभी तक एक उदाहरण नहीं दिया है, इसलिए यहां मेरा है:

string number = "(\\d+)";
string unit = "(?:" + number + "\\s*:\\s*)";
string optionalDecimal = "(?:\\s*[.,]\\s*" + number + ")?";

Pattern re = Pattern.compile(
  "^\\s*(?:" + unit + "?" + unit + ")?" + number + optionalDecimal + "\\s*$"
);

सबसे पठनीय नहीं है, लेकिन मुझे लगता है कि यह मूल की तुलना में स्पष्ट है।

इसके अलावा, सी # है @ऑपरेटर जो आदेश इंगित करने के लिए यह सचमुच (कोई भागने अक्षर) ले जाया जा रहा है कि में एक स्ट्रिंग के लिए prepended किया जा सकता है, तो numberहो सकता है@"([\d]+)";


अभी-अभी देखा कि कैसे दोनों [\\d]+और [0-9]+बस होना चाहिए \\d+(ठीक है, कुछ [0-9]+अधिक पठनीय हो सकता है )। मैं प्रश्न को संपादित नहीं करने जा रहा हूं, लेकिन आप इस उत्तर को ठीक करना चाह सकते हैं।
हाईड

@ प्रेस - अच्छी पकड़। तकनीकी रूप से वे एक ही चीज़ नहीं हैं - \dकिसी भी संख्या से मेल खाने वाली किसी भी चीज़ से मेल खाएंगे, यहां तक ​​कि अन्य नंबरिंग सिस्टम (चीनी, अरबी, आदि) में भी, जबकि [0-9]बस मानक अंकों से मेल खाएगा। \\dहालांकि, मैंने इसे मानकीकृत किया , और इसे optionalDecimalपैटर्न में शामिल किया।
बोबसन

42

नियमित अभिव्यक्ति का दस्तावेजीकरण करने की कुंजी यह दस्तावेज है। बहुत दूर लोग अक्सर लाइन शोर में दिखाई देते हैं और उस पर छोड़ देते हैं।

नियमित अभिव्यक्ति के अंत में perl/x ऑपरेटर के भीतर एक व्हाट्सएप को दबा देता है जिससे व्यक्ति नियमित अभिव्यक्ति का दस्तावेज बना सकता है।

उपरोक्त नियमित अभिव्यक्ति तब बनेगी:

$re = qr/
  ^\s*
  (?:
    (?:       
      ([\d]+)\s*:\s*
    )?
    (?:
      ([\d]+)\s*:\s*
    )
  )?
  ([\d]+)
  (?:
    \s*[.,]\s*([\d]+)
  )?
  \s*$
/x;

हां, इसका थोड़ा सा वर्टिकल व्हॉट्सएप का सेवन, हालांकि बहुत अधिक पठनीयता का त्याग किए बिना इसे छोटा कर सकता है।

और फिर, पहले वाला रेग्जैक्स यह क्या करता है: प्रारूप 1: 2: 3.4 में संख्याओं की एक स्ट्रिंग को पार्स करें, प्रत्येक संख्या को कैप्चर करना, जहां रिक्त स्थान की अनुमति है और केवल 3 की आवश्यकता है।

इस नियमित अभिव्यक्ति को देखकर कोई भी यह देख सकता है कि यह कैसे काम करता है (और काम नहीं करता है)। इस मामले में, यह रेगेक्स स्ट्रिंग से मेल खाएगा 1

इसी तरह के दृष्टिकोण अन्य भाषा में लिए जा सकते हैं। अजगर re.VERBOSE विकल्प वहाँ काम करता है।

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

जावा में (जहां यह उदाहरण से आरेखित होता है), कोई रेगेक्स बनाने के लिए स्ट्रिंग संघनन का उपयोग कर सकता है।

Pattern re = Pattern.compile(
  "^\\s*"+
  "(?:"+
    "(?:"+
      "([\\d]+)\\s*:\\s*"+  // Capture group #1
    ")?"+
    "(?:"+
      "([\\d]+)\\s*:\\s*"+  // Capture group #2
    ")"+
  ")?"+ // First groups match 0 or 1 times
  "([\\d]+)"+ // Capture group #3
  "(?:\\s*[.,]\\s*([0-9]+))?"+ // Capture group #4 (0 or 1 times)
  "\\s*$"
);

जाहिर है, यह "स्ट्रिंग में कई और अधिक पैदा करता है, जिससे संभवतः वहां कुछ भ्रम पैदा हो सकता है, अधिक आसानी से पढ़ा जा सकता है (विशेषकर अधिकांश आईडीई पर वाक्य रचना हाइलाइटिंग के साथ) और प्रलेखित।

कुंजी शक्ति को पहचान रही है और "एक बार लिखो" प्रकृति है कि नियमित अभिव्यक्ति अक्सर गिर जाती है। कोड को रक्षात्मक रूप से लिखने से बचें ताकि नियमित अभिव्यक्ति स्पष्ट रहे और समझने योग्य हो। हम जावा कोड को स्पष्टता के लिए प्रारूपित करते हैं - नियमित अभिव्यक्तियाँ अलग नहीं हैं जब भाषा आपको ऐसा करने का विकल्प देती है।


13
"डॉक्यूमेंटिंग" और "लाइन ब्रेक जोड़ने" के बीच एक बड़ा अंतर है।

4
@JonofAllTrades कोड को पढ़ने में सक्षम बनाना किसी भी चीज़ के लिए पहला कदम है। लाइन ब्रेक जोड़ने से एक ही लाइन पर आरई के उस सबसेट के लिए टिप्पणियां जोड़ने की अनुमति मिलती है (कुछ जो नियमित अभिव्यक्ति पाठ की एक लंबी लाइन पर करना अधिक कठिन है)।

2
@JonofAllTrades, मैं बहुत दृढ़ता से असहमत हूं। "डॉक्यूमेंटिंग" और "लाइन ब्रेक जोड़ना" अलग नहीं हैं, जिसमें वे दोनों एक ही उद्देश्य से काम करते हैं - कोड को समझना आसान बनाता है। और खराब-स्वरूपित कोड के लिए, "लाइन ब्रेक को जोड़ना" उस उद्देश्य को पूरा करता है जो कि प्रलेखन को जोड़ने से बेहतर होता है।
बेन ली

2
लाइन ब्रेक जोड़ना एक शुरुआत है, लेकिन यह लगभग 10% नौकरी है। अन्य उत्तर अधिक बारीकियां देते हैं, जो सहायक है।

26

कुछ भाषाओं और पुस्तकालयों द्वारा प्रस्तुत "वर्बोज़" मोड इन चिंताओं के जवाबों में से एक है। इस मोड में, regexp स्ट्रिंग में व्हाट्सएप छीन लिया जाता है (इसलिए आपको उपयोग करने की आवश्यकता है \s) और टिप्पणियां संभव हैं। यहाँ पायथन में एक छोटा उदाहरण दिया गया है जो डिफ़ॉल्ट रूप से इसका समर्थन करता है:

email_regex = re.compile(r"""
    ([\w\.\+]+) # username (captured)
    @
    \w+         # minimal viable domain part
    (?:\.w+)    # rest of the domain, after first dot
""", re.VERBOSE)

किसी भी भाषा में, जो अनुवादक को क्रिया से "सामान्य" मोड में लागू नहीं करता है, एक सरल कार्य होना चाहिए। यदि आप अपने regexps की पठनीयता के बारे में चिंतित हैं, तो आप शायद इस बार के निवेश को बहुत आसानी से उचित ठहराएंगे।


15

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

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


1
उत्तर की शुरुआत में उल्लिखित "सरल ब्लॉकों" से, क्या आपका मतलब सिर्फ स्ट्रिंग संयोजन, या कुछ और अधिक उन्नत है?
हाईड

7
मेरा मतलब था उप-अभिव्यक्तियों को छोटे स्ट्रिंग शाब्दिक के रूप में परिभाषित करना, उन्हें सार्थक नामों के साथ स्थानीय चर को निर्दिष्ट करना, और फिर संक्षिप्त करना। मुझे लगता है कि नाम केवल लेआउट सुधार से पठनीयता के लिए अधिक महत्वपूर्ण हैं।
किलन फ़ॉथ

11

मुझे Expresso: http://www.ultrapico.com/Expresso.htm का उपयोग करना पसंद है

इस मुफ्त एप्लिकेशन में निम्नलिखित विशेषताएं हैं जो मुझे समय के साथ उपयोगी लगती हैं:

  • आप बस अपने रेगेक्स को कॉपी और पेस्ट कर सकते हैं और एप्लिकेशन आपके लिए इसे पार्स कर देगा
  • एक बार जब आपका रेगेक्स लिखा जाता है, तो आप इसे सीधे आवेदन से जांच सकते हैं (आवेदन आपको कैप्चर, प्रतिस्थापन की सूची देगा ...)
  • एक बार जब आप इसका परीक्षण कर लेते हैं, तो यह इसे लागू करने के लिए सी # कोड उत्पन्न करेगा (ध्यान दें कि कोड में आपके रेगेक्स के बारे में स्पष्टीकरण होगा)।

उदाहरण के लिए, रेगेक्स के साथ आपने अभी प्रस्तुत किया है, यह ऐसा दिखेगा: शुरुआत में रेगेक्स के साथ नमूना स्क्रीन

बेशक, यह एक कोशिश दे एक हजार शब्द का वर्णन करने के लायक है। कृपया ध्यान दें कि मैं इस एप्लिकेशन के संपादक के साथ किसी भी तरह से संबंधित हूं।


4
क्या आप इस बारे में और अधिक विस्तार से बताएंगे - यह पूछे गए प्रश्न का उत्तर कैसे और क्यों देता है? "लिंक-ओनली जवाब" स्टैक एक्सचेंज में बहुत स्वागत नहीं है
gnat

5
@gnat इसके बारे में क्षमा करें। आप बिल्कुल सही कह रहे है। मुझे उम्मीद है कि मेरा संपादित जवाब अधिक अंतर्दृष्टि प्रदान करता है।
ई। जेप

9

कुछ चीजों के लिए, यह सिर्फ BNF जैसे व्याकरण का उपयोग करने में मदद कर सकता है। ये नियमित अभिव्यक्ति की तुलना में पढ़ने में बहुत आसान हो सकते हैं। इसके बाद GoldParser Builder जैसा टूल व्याकरण को एक ऐसे पार्सर में बदल देता है जो आपके लिए भारी लिफ्टिंग करता है।

बीएनएफ, ईबीएनएफ, आदि व्याकरण एक जटिल नियमित अभिव्यक्ति की तुलना में पढ़ने और बनाने में बहुत आसान हो सकते हैं। ऐसी चीजों के लिए सोना एक साधन है।

नीचे दिए गए सी 2 विकी लिंक में संभावित विकल्पों की एक सूची है, जिन्हें गुगली किया जा सकता है, जिसमें उन पर कुछ चर्चा भी शामिल है। यह मूल रूप से "व्याकरण इंजन अनुशंसा" को बंद करने के लिए एक "देखें" लिंक भी है:

नियमित अभिव्यक्तियों के लिए विकल्प

"वैकल्पिक" का अर्थ "अलग-अलग वाक्यविन्यास के साथ शब्दार्थ रूप से समतुल्य सुविधा" लेना, कम से कम इन विकल्पों के साथ / नियमित नियम के साथ हैं:

  • बुनियादी नियमित अभिव्यक्ति
  • "विस्तारित" नियमित अभिव्यक्ति
  • पर्ल-संगत नियमित अभिव्यक्ति
  • ... और कई अन्य संस्करण ...
  • SNOBOL- शैली आरई वाक्य रचना (स्नोबोल भाषा, IconLanguage)
  • एसआरई सिंटैक्स (आरईएस के रूप में निबंध)
  • अलग FSM वाक्यविन्यास
  • परिमित राज्य चौराहे व्याकरण (काफी अभिव्यंजक)
  • ParsingExpressionGrammars, OMetaLanguage और LuaLanguage ( http://www.inf.puc-rio.br/~roberto/lpeg/lpeg.html ) के रूप में
  • RebolLanguage का पार्स मोड
  • ProbabilityBasedParsing ...

क्या आप इस लिंक पर क्या करते हैं और इसके लिए क्या अच्छा है, इस बारे में अधिक जानकारी प्राप्त करने का मन करेगा? "लिंक-ओनली उत्तर" का स्टैक एक्सचेंज में बहुत स्वागत नहीं है
gnat

1
प्रोग्रामर्स में आपका स्वागत है, निक पी। कृपया डाउनवोट / आर को नजरअंदाज करें, लेकिन मेटा @ से जुड़े लिंक पर पेज पढ़ें।
क्रिस्टोफर लेप्टे

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

6

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

// Create an example of how to test for correctly formed URLs
var tester = VerEx()
    .startOfLine()
    .then('http')
    .maybe('s')
    .then('://')
    .maybe('www.')
    .anythingBut(' ')
    .endOfLine();

// Create an example URL
var testMe = 'https://www.google.com';

// Use RegExp object's native test() function
if (tester.test(testMe)) {
    alert('We have a correct URL '); // This output will fire}
} else {
    alert('The URL is incorrect');
}

console.log(tester); // Outputs the actual expression used: /^(http)(s)?(\:\/\/)(www\.)?([^\ ]*)$/

यह उदाहरण जावास्क्रिप्ट के लिए है, आप इस लाइब्रेरी को अब कई प्रोग्रामिंग भाषाओं के लिए पा सकते हैं।


2
यह कमाल का है!
जेरेमी थॉम्पसन

3

सबसे सरल तरीका अभी भी रेगेक्स का उपयोग करना होगा, लेकिन वर्णनात्मक नामों के साथ सरल अभिव्यक्तियों की रचना से अपनी अभिव्यक्ति का निर्माण करें जैसे कि http://www.martinfowler.com/bliki/ComposedRegex.html (और हाँ यह स्ट्रिंग कॉन्कटैट से है

हालांकि एक विकल्प के रूप में आप एक पार्सर कॉम्बीनेटर लाइब्रेरी का उपयोग कर सकते हैं जैसे http://jparsec.codehaus.org/ जो आपको एक पूर्ण पुनरावर्ती सभ्य पार्सर देगा। फिर से यहां वास्तविक शक्ति रचना (इस समय कार्यात्मक रचना) से आती है।


3

मैंने सोचा कि यह logstash के उल्लेख के लायक हो जाएगा grok भाव। ग्रोक छोटे लोगों से लंबे पार्सिंग भावों की रचना करने के विचार पर बनाता है। यह इन इमारत ब्लॉकों के सुविधाजनक परीक्षण की अनुमति देता है और 100 से अधिक आमतौर पर उपयोग किए जाने वाले पैटर्न के साथ आता है । इन पैटर्नों के अलावा, यह सभी नियमित अभिव्यक्तियों के सिंटैक्स का उपयोग करने की अनुमति देता है।

उपर्युक्त प्रतिमान खांचे में व्यक्त किया गया है (मैंने डिबगर ऐप में परीक्षण किया है, लेकिन गड़बड़ी हो सकती है):

"(( *%{NUMBER:a} *:)? *%{NUMBER:b} *:)? *%{NUMBER:c} *(. *%{NUMBER:d} *)?"

वैकल्पिक भागों और रिक्त स्थान सामान्य से थोड़ा बदसूरत लगते हैं, लेकिन यहां और अन्य मामलों में, खांचे का उपयोग करके किसी के जीवन को बहुत अच्छा बना सकते हैं।


2

F # में आपके पास FsVerbalExpressions मॉड्यूल है। यह आपको मौखिक अभिव्यक्तियों से रेगेक्स की रचना करने की अनुमति देता है, इसमें कुछ पूर्व-निर्मित रीगेक्स (जैसे URL) भी हैं।

इस सिंटैक्स के लिए एक उदाहरण निम्नलिखित है:

let groupName =  "GroupNumber"

VerbEx()
|> add "COD"
|> beginCaptureNamed groupName
|> any "0-9"
|> repeatPrevious 3
|> endCapture
|> then' "END"
|> capture "COD123END" groupName
|> printfn "%s"

// 123

यदि आप F # सिंटैक्स से परिचित नहीं हैं, तो GroupName स्ट्रिंग "GroupNumber" है।

फिर वे एक वर्बल एक्सप्रेशन (VerbEx) बनाते हैं जो वे "COD (? <GroupNumber> [0-9] {3}) END" के रूप में बनाते हैं। जिसके बाद वे स्ट्रिंग "COD123END" पर परीक्षण करते हैं, जहां उन्हें नामित कैप्चर समूह "GroupNumber" मिलता है। यह 123 में परिणाम है।

मैं ईमानदारी से सामान्य रेगेक्स को समझने में बहुत आसान लगता हूं।


-2

सबसे पहले, उस कोड को समझें जो केवल काम करता है बुरा कोड। अच्छा कोड भी किसी भी त्रुटि का सामना करने के लिए सही रिपोर्ट की जरूरत है।

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

अब अपने "पैरा 1: 2: 3.4" उदाहरण में संख्याओं की एक स्ट्रिंग के बारे में सोचें। सभी रेगेक्स रिपोर्ट "पास / फेल" है जो उपयोगकर्ता को पर्याप्त प्रतिक्रिया देने की अनुमति नहीं देता है (चाहे यह प्रतिक्रिया लॉग में त्रुटि संदेश हो, या एक इंटरैक्टिव जीयूआई है जहां त्रुटियों को लाल रंग में दिखाया गया है। उपयोगकर्ता प्रकार, या जो कुछ भी)। ठीक से वर्णन करने में किस प्रकार की त्रुटियां हैं? पहली संख्या में खराब चरित्र, पहली संख्या बहुत बड़ी, पहली संख्या के बाद लापता बृहदान्त्र आदि।

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

कोड को पठनीय / सुवाह्य बनाना कोड को अच्छा बनाने का एक आकस्मिक परिणाम है।


6
शायद अच्छी धारणा नहीं है। मेरा है, क्योंकि ए) इस सवाल को संबोधित नहीं करता ( कैसे यह पठनीय बनाने के लिए?), बी) नियमित अभिव्यक्ति मिलान है पास / असफल, और आप इसे बिंदु है जहां आप वास्तव में कह सकते हैं क्यों यह असफल करने के लिए तोड़ने के नीचे हैं, तो आप बहुत अधिक शक्ति और गति खो देते हैं, और जटिलता को बढ़ाते हैं, C) इस प्रश्न से कोई संकेत नहीं मिलता है कि मैच के असफल होने की संभावना भी है - यह केवल रेगेक्स को पठनीय बनाने के बारे में एक प्रश्न है। जब आपके पास हाथ में जाने और / या इसे सत्यापित करने से पहले डेटा का नियंत्रण होता है, तो आप मान सकते हैं कि यह वैध है।
बोबसन

ए) इसे छोटे टुकड़ों में तोड़ना इसे अधिक पठनीय बनाता है (इसे अच्छा बनाने के परिणामस्वरूप)। ग) जहां अज्ञात / अनवांटेड स्ट्रिंग्स सॉफ्टवेयर के एक टुकड़े को दर्ज करते हैं, उस बिंदु पर एक डेवलपर डेवलपर पार्स (त्रुटि रिपोर्टिंग के साथ) पार्स करेगा और डेटा को ऐसे रूप में परिवर्तित कर देगा जिसे पुन: भरने की आवश्यकता नहीं है - उसके बाद regex की आवश्यकता नहीं है। बी) बकवास है जो केवल खराब कोड (अंकों ए और सी का संदर्भ) पर लागू होता है।
ब्रेंडन

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

यदि यह "C: सत्यापन (त्रुटि रिपोर्टिंग के साथ)" है तो यह खराब कोड है क्योंकि त्रुटि रिपोर्टिंग खराब है। यदि यह विफल रहता है; क्या यह इसलिए था क्योंकि स्ट्रिंग NULL थी, या क्योंकि पहले नंबर पर बहुत सारे अंक थे, या क्योंकि पहला विभाजक नहीं था :? एक कंपाइलर की कल्पना करें जिसमें केवल एक त्रुटि संदेश ("ERROR") था जो उपयोगकर्ता को यह बताने के लिए बहुत बेवकूफ था कि समस्या क्या है। अब हज़ारों वेब साइटों की कल्पना करें जो सिर्फ बेवकूफ हैं और प्रदर्शन (जैसे) "खराब ईमेल पता" और इससे अधिक कुछ नहीं।
ब्रेंडन

इसके अलावा, एक आधे प्रशिक्षित हेल्प डेस्क ऑपरेटर की कल्पना करें जो पूरी तरह से अप्रशिक्षित उपयोगकर्ता से बग रिपोर्ट प्राप्त कर रहा है: सॉफ़्टवेयर ने काम करना बंद कर दिया - सॉफ़्टवेयर के लॉग में अंतिम पंक्ति "ERROR: संस्करण स्ट्रिंग से मामूली संस्करण संख्या निकालने में विफल रहा है '1: 2-3.4 '(दूसरे नंबर के बाद अपेक्षित बृहदान्त्र) "
ब्रेंडन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.