नेस्टेड कैप्चरिंग समूहों को नियमित अभिव्यक्तियों में कैसे गिना जाता है?


84

क्या एक परिभाषित व्यवहार है कि नियमित भावों को नेस्टेड कोष्ठक के कैप्चरिंग व्यवहार को कैसे संभालना चाहिए? अधिक विशेष रूप से, क्या आप यथोचित अपेक्षा कर सकते हैं कि विभिन्न इंजन पहली स्थिति में बाहरी कोष्ठक पर कब्जा करेंगे, और बाद के पदों में निहित कोष्ठक?

निम्नलिखित PHP कोड पर विचार करें (PCRE नियमित अभिव्यक्ति का उपयोग करके)

<?php
  $test_string = 'I want to test sub patterns';
  preg_match('{(I (want) (to) test) sub (patterns)}', $test_string, $matches);
  print_r($matches);
?>

Array
(
    [0] => I want to test sub patterns  //entire pattern
    [1] => I want to test           //entire outer parenthesis
    [2] => want             //first inner
    [3] => to               //second inner
    [4] => patterns             //next parentheses set
)

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

तो, क्या यह "पूरी चीज़ को पहले कैप्चर करता है" नियमित अभिव्यक्ति इंजन में परिभाषित व्यवहार, या क्या यह पैटर्न और / या इंजन के व्यवहार के संदर्भ पर निर्भर करने वाला है (PCRE C # की तुलना में भिन्न होने के नाते जावा के अलग होने से भिन्न है) आदि से)?


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

समूह को $ 1, $ 2, $ 3 .... आदि का उपयोग करके पहुँचा जा सकता है। 10 वें समूह तक कैसे पहुंचें? क्या यह $ 10 होगा? मुझे नहीं लगता कि $ 10 काम करेगा क्योंकि इसकी व्याख्या $ 1 के बाद होगी। इसका मतलब यह है कि हमारे पास अधिकतम 9 समूह ही हो सकते हैं? यदि लेखक कृपया, इसे प्रश्न के भाग के रूप में शामिल कर सकता है, तो नियमित अभिव्यक्तियों में नेस्टेड समूहों के बारे में जानने के लिए यह एकल स्थान होगा।
लायनहार्ट

जवाबों:


59

से perlrequick

यदि रेगेक्स में समूहों को नेस्टेड किया जाता है, तो $ 1 को समूह सबसे बाईं ओर के उद्घाटन कोष्ठक के साथ मिलता है, $ 2 अगले उद्घाटन कोष्ठक, आदि।

कैविएट : गैर-कैप्चर समूह को खोलने वाले कोष्ठक को छोड़कर (? =)

अपडेट करें

मैं पीसीआरई का अधिक उपयोग नहीं करता हूं, जैसा कि मैं आम तौर पर वास्तविक चीज का उपयोग करता हूं;), लेकिन पीसीआरई के डॉक्स पर्ल के समान हैं:

SUBPATTERNS

2.यह उप-कैप्चर को उप-कैप्चरिंग के रूप में सेट अप करता है। इसका मतलब यह है कि, जब पूरे पैटर्न का मिलान होता है, तो सब्जेक्टटेन से मिलान करने वाले विषय स्ट्रिंग के उस हिस्से को कॉल करने वाले के पास वापस भेजा जाता ovectorहै pcre_exec()। ओपनिंग कोष्ठक को बाएं से दाएं (1 से शुरू) तक गिना जाता है ताकि कैप्चरिंग सबपैटर्न के लिए नंबर प्राप्त किया जा सके।

उदाहरण के लिए, यदि स्ट्रिंग "लाल राजा" पैटर्न के खिलाफ मेल खाता है

the ((red|white) (king|queen))

कब्जा कर लिया substrings "लाल राजा", "लाल", और "राजा" हैं, और क्रमशः 1, 2, और 3 गिने जाते हैं।

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


1
@ सीन: वह PHP में PCRE का उपयोग कर रहा है, जो कि "पर्ल-कम्पेटिबल रेगुलर एक्सप्रेशंस" है; इसलिए यह सीधे पर्ल का उपयोग करने के समान है
पास्कल मार्टिन

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

1
दरअसल, यह पर्ल है जो इन दिनों "ड्रिफ्टिंग दूर" का सबसे अधिक काम कर रहा है, लेकिन आप सही हैं: "पर्ल-संगत" एक मिथ्या नाम से एक गैर सीक्वेटुर में जल्दी से बदल रहा है। : D
एलन मूर

1
@ एलन, पर्ल निश्चित रूप से आगे बढ़ रहा है। P5.10 ने कुछ चीजों को बदल दिया, लेकिन 6 बहुत अलग होंगे। पी को लगभग निश्चित रूप से "पर्ल 5" के रूप में व्याख्या करने की आवश्यकता होगी। पीसीआरई एक बेहतरीन परियोजना है, जिसकी मैं पर्याप्त प्रशंसा नहीं कर सकता, यह कुछ परियोजनाओं से अधिक पर एक गॉडसेंड रहा है।
दतोआद

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

17

हाँ, यह उन सभी भाषाओं के लिए बहुत अच्छी तरह से परिभाषित है जिन्हें आप में रुचि रखते हैं:

  • जावा - http://java.sun.com/javase/6/docs/api/java/util/regex/Pattern.html#cg
    "कैप्चरिंग समूहों को उनके शुरुआती कोष्ठकों को बाएं से दाएं की गिनती करके गिना जाता है ... समूह। शून्य हमेशा पूरी अभिव्यक्ति के लिए खड़ा होता है। "
  • .Net - http://msdn.microsoft.com/en-us/library/bs2twtah(VS.71).aspx
    "का उपयोग करके कैप्चर () एक से शुरू होने वाले शुरुआती कोष्ठक के क्रम के आधार पर स्वचालित रूप से गिने जाते हैं। पहला। कैप्चर, कैप्चर एलिमेंट नम्बर जीरो, पूरे रेगुलर एक्सप्रेशन पैटर्न द्वारा मैच किया गया टेक्स्ट है। ")
  • PHP (PCRE फ़ंक्शन) - http://www.php.net/manual/en/function.preg-replace.php#function.preg-replace.parameters
    "\ 0 या $ 0 पूरे पैटर्न द्वारा मेल किए गए पाठ को संदर्भित करता है। कैप्चरिंग सबपैटर्न की संख्या प्राप्त करने के लिए ओपनिंग कोष्ठक को बाएं से दाएं (1 से शुरू) में गिना जाता है। " (यह पदावनत POSIX कार्यों का भी सच था)
  • PCRE - http://www.pcre.org/pcre.txt
    एलन एम ने जो कहा, उसे जोड़ने के लिए, "कैसे pcre_exec () कैप्चर किए गए सब्सट्रेट रिटर्न" खोजें और इसके बाद आने वाले पांचवें पैराग्राफ को पढ़ें:

    पूर्णांक की पहली जोड़ी, ovector [0] और ovector [1], की पहचान करें
    पूरे पैटर्न द्वारा मिलान किए गए विषय स्ट्रिंग का हिस्सा। अगला
    जोड़ी का उपयोग पहली कैप्चरिंग सबपैटर्न के लिए किया जाता है, और इसी तरह। महत्व
    pcre_exec () द्वारा लौटाया गया सबसे अधिक संख्या वाली जोड़ी से एक अधिक है
    निर्धारित किया गया है। उदाहरण के लिए, यदि दो सबस्ट्रिंग कैप्चर किए गए हैं, तो
    लौटाया गया मूल्य 3. यदि कोई उप-कैप्चरिंग कैप्चरिंग नहीं है, तो रिटर्न
    एक सफल मैच से मूल्य 1 है, यह दर्शाता है कि सिर्फ पहली जोड़ी है
    ऑफसेट सेट किया गया है।
    
  • पर्ल का अलग - http://perldoc.perl.org/perlre.html#Capture-buffers
    $ 1, $ 2 आदि के रूप में आप उम्मीद करेंगे (जैसे कि कोष्ठक खोलने की घटना से) समूहों को कैप्चर करते हैं, हालाँकि $ 0 प्रोग्राम का नाम लौटाता है, नहीं संपूर्ण क्वेरी स्ट्रिंग - यह प्राप्त करने के लिए कि आप $ का उपयोग करते हैं और इसके बजाय।

आप अन्य भाषाओं (पायथन, रूबी और अन्य) के लिए समान परिणाम प्राप्त करने की संभावना से अधिक होंगे।

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

पूरे मैच स्ट्रिंग को 0 की स्थिति में रखना भी समझ में आता है - ज्यादातर स्थिरता के लिए। यह पूरी तरह से मिलान किए गए स्ट्रिंग को एक ही इंडेक्स पर बनाए रखने की अनुमति देता है, चाहे रेजगेक्स से रेगेक्स पर संख्या कैप्चर करने वाले समूहों की परवाह किए बिना और उन कैप्चरिंग समूहों की संख्या की परवाह किए बिना जो वास्तव में कुछ भी मैच करते हैं (उदाहरण के लिए जावा मिलान किए गए समूहों की लंबाई को प्रत्येक कैप्चरिंग के लिए संक्षिप्त कर देगा समूह किसी भी सामग्री से मेल नहीं खाता (उदाहरण के लिए "a (। *) पैटर्न" जैसी किसी चीज़ के बारे में सोचें)। आप हमेशा कैप्चरिंग_ग्रेग_्रेसल्ट्स [कैप्चरिंग_ग्रुप_्रेसुल्स_लग्मेंट - 2] का निरीक्षण कर सकते हैं, लेकिन यह पेरेल की भाषाओं में अच्छी तरह से अनुवाद नहीं करता है जो गतिशील रूप से चर बनाते हैं ($ 1) , $ 2 आदि) (पर्ल का निश्चित रूप से एक बुरा उदाहरण है, क्योंकि यह मेल खाते हुए अभिव्यक्ति के लिए $ और का उपयोग करता है, लेकिन आपको यह विचार प्राप्त होता है :)।


1
अच्छा जवाब .. लेकिन कैसे अजगर (2 और 3) के लिए अद्यतन करने के बारे में भी :-)
JGFMK

जावास्क्रिप्ट के बारे में क्या!?!
मेस्क्यूब

9

प्रत्येक regex स्वाद मुझे पता है कि संख्या समूह उस क्रम से है जिसमें शुरुआती कोष्ठक दिखाई देते हैं। बाहरी समूहों को उनके निहित उप-समूहों से पहले गिना जाता है, यह केवल एक स्वाभाविक परिणाम है, स्पष्ट नीति नहीं।

जहां यह दिलचस्प हो जाता है नामांकित समूहों के साथ । ज्यादातर मामलों में, वे पार्न्स के रिश्तेदार पदों द्वारा क्रमांकन की एक ही नीति का पालन करते हैं - नाम केवल संख्या के लिए एक उपनाम है। हालाँकि, .NET regexes में नामांकित समूहों को क्रमांकित समूहों से अलग से क्रमांकित किया गया है। उदाहरण के लिए:

Regex.Replace(@"one two three four", 
              @"(?<one>\w+) (\w+) (?<three>\w+) (\w+)",
              @"$1 $2 $3 $4")

// result: "two four one three"

वास्तव में, संख्या के लिए एक उपनाम है नाम ; नामित समूहों को सौंपी गई संख्याएं शुरू होती हैं, जहां "वास्तविक" गिने समूह बंद हो जाते हैं। यह एक विचित्र नीति की तरह लग सकता है, लेकिन इसके लिए एक अच्छा कारण है: .NET regexes में आप एक ही समूह के नाम का उपयोग एक से अधिक बार regex में कर सकते हैं। विभिन्न स्थानों से फ्लोटिंग-पॉइंट नंबरों के मिलान के लिए इस धागे से एक के समान ही संभव बनाता है :

^[+-]?[0-9]{1,3}
(?:
    (?:(?<thousand>\,)[0-9]{3})*
    (?:(?<decimal>\.)[0-9]{2})?
|
    (?:(?<thousand>\.)[0-9]{3})*
    (?:(?<decimal>\,)[0-9]{2})?
|
    [0-9]*
    (?:(?<decimal>[\.\,])[0-9]{2})?
)$

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

और उसके बाद पर्ल 5.10+ है, जो मुझे उन समूहों पर कब्जा करने से अधिक नियंत्रण देता है, जो मुझे पता है कि मुझे क्या करना है। : डी


4

बाएं पैरेन के क्रम में कैप्चरिंग का क्रम उन सभी प्लेटफार्मों पर मानक है, जिनमें मैंने काम किया है। (perl, php, ruby, egrep)


"बाएं पेरेन के क्रम में कैप्चरिंग" इसके लिए धन्यवाद, यह व्यवहार का वर्णन करने का एक बहुत अधिक सफल तरीका है।
एलन स्टॉर्म

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