संतुलित कोष्ठकों से मेल खाने की नियमित अभिव्यक्ति


290

मुझे दो बाहरी कोष्ठक के बीच सभी पाठ का चयन करने के लिए एक नियमित अभिव्यक्ति की आवश्यकता है।

उदाहरण: some text(text here(possible text)text(possible text(more text)))end text

परिणाम: (text here(possible text)text(possible text(more text)))


3
यह प्रश्न बहुत खराब है क्योंकि यह स्पष्ट नहीं है कि यह क्या पूछ रहा है। सभी उत्तरों ने इसकी अलग-अलग व्याख्या की। @ क्या आप सवाल को स्पष्ट कर सकते हैं?
मैट फेनविक

1
इस पोस्ट में उत्तर दिया गया: stackoverflow.com/questions/6331065/…
sship21

जवाबों:


144

नियमित अभिव्यक्ति नौकरी के लिए गलत उपकरण है क्योंकि आप नेस्टेड संरचनाओं के साथ काम कर रहे हैं, अर्थात पुनरावृत्ति।

लेकिन वहाँ यह करने के लिए एक सरल एल्गोरिथ्म, जो मैं वर्णित है इस जवाब में एक करने के लिए पिछले प्रश्न


15
.NET के कार्यान्वयन में [बैलेंसिंग ग्रुप परिभाषाएँ msdn.microsoft.com/en-us/library/… है जो इस प्रकार की अनुमति देता है।
कार्ल जी

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


20
रेगेक्स नौकरी के लिए राइट टूल है। यह उत्तर सही नहीं है। देखें rogal111 का जवाब।
एंड्रयू

4
जवाब से बिल्कुल सहमत हैं। हालाँकि regexp में पुनरावृत्ति के कुछ कार्यान्वयन हैं, वे परिमित-राज्य मशीनों के बराबर हैं और नेस्टेड संरचनाओं के साथ काम करने के लिए दबाए नहीं जाते हैं, लेकिन संदर्भ मुक्त व्याकरण ऐसा करते हैं। औपचारिक ग्रामर की होम्सकी की पदानुक्रम को देखें।
निक रोज 10

138

मैं इस जवाब को त्वरितता के लिए जोड़ना चाहता हूं। अद्यतन करने के लिए स्वतंत्र महसूस करें।


.NET बैलेंसिंग समूहों का उपयोग करके रेगेक्स

\((?>\((?<c>)|[^()]+|\)(?<-c>))*(?(c)(?!))\)

जहां cगहराई काउंटर के रूप में उपयोग किया जाता है।

Regexstorm.com पर डेमो


एक पुनरावर्ती पैटर्न का उपयोग कर पीसीआरई

\((?:[^)(]+|(?R))*+\)

Regex101 पर डेमो ; या वैकल्पिक के बिना:

\((?:[^)(]*(?R)?)*+\)

Regex101 पर डेमो ; या प्रदर्शन के लिए अनियंत्रित :

\([^)(]*+(?:(?R)[^)(]*)*+\)

Regex101 पर डेमो ; पैटर्न को चिपकाया जाता है (?R)जिस पर प्रतिनिधित्व होता है (?0)

पर्ल, पीएचपी, नोटपैड ++, आर : पर्ल = सही , पायथन : Regex पैकेज के साथ (?V1)पर्ल व्यवहार के लिए।


रूबी सबफ़्लेशन कॉल्स का उपयोग करते हुए ।

रूबी के साथ 2.0 \g<0>का उपयोग पूर्ण पैटर्न को कॉल करने के लिए किया जा सकता है।

\((?>[^)(]+|\g<0>)*\)

Rubular पर डेमो ; रूबी 1.9 केवल कैप्चरिंग ग्रुप रिकर्सन का समर्थन करती है :

(\((?>[^)(]+|\g<1>)*\))

रूबुलर में डेमो  ( रूबी 1.9.3 के बाद से परमाणु समूहन )


जावास्क्रिप्ट   एपीआई :: XRegExp.matchRecursive

XRegExp.matchRecursive(str, '\\(', '\\)', 'g');

जेएस, जावा और अन्य रेगेक्स फ्लेवर बिना नेस्टिंग के 2 स्तरों तक:

\((?:[^)(]+|\((?:[^)(]+|\([^)(]*\))*\))*\)

Regex101 पर डेमो करें । डीपर नेस्टिंग को पैटर्न में जोड़ने की जरूरत है
असंतुलित कोष्ठक पर तेजी से विफल करने के लिए लिए +मात्रा को गिरा दें ।


जावा : @ संजय द्वारा आगे के संदर्भों का उपयोग करते हुए एक दिलचस्प विचार


संदर्भ - इस रेगेक्स का क्या अर्थ है?


1
जब आप एक समूह को एक मात्रात्मक मात्रा के साथ दोहराते हैं, तो उस समूह को परमाणु बनाना बेकार है क्योंकि उस समूह के सभी पीछे के स्थान को प्रत्येक पुनरावृत्ति में हटा दिया जाता है। इसलिए लिखना लिखने (?>[^)(]+|(?R))*+की तुलना में एक ही है (?:[^)(]+|(?R))*+। अगले पैटर्न के लिए एक ही बात। अनियंत्रित संस्करण के बारे में, आप यहां एक प्रभावशाली मात्रा निर्धारित कर सकते हैं: [^)(]*+बैकट्रैकिंग को रोकने के लिए (यदि कोई समापन ब्रैकेट नहीं है)।
कासिमिर एट हिप्पोलाइट

बारे में रूबी 1.9 पैटर्न, बजाय दोहराया समूह परमाणु (जब वहाँ कई नेस्टेड कोष्ठक हैं एक सीमित दिलचस्पी है कि बनाने का (...(..)..(..)..(..)..(..)..)विषय स्ट्रिंग में)), तो आपको एक परमाणु समूह में सभी संलग्न एक सरल गैर पर कब्जा समूह का उपयोग कर सकते हैं और: (?>(?:[^)(]+|\g<1>)*)( यह एक अधिकारपूर्ण मात्रात्मक की तरह व्यवहार करता है)। रूबी 2.x में, प्रथक क्वांटिफायर उपलब्ध है।
कासिमिर एट हिप्पोलाइट

@CasimiretHippolyte धन्यवाद! मैंने पीसीआरई पैटर्न को समायोजित किया और रूबी 1.9 के लिए, क्या आपका मतलब है कि पूरे पैटर्न इस तरह से हैं ? कृपया खुद को अपडेट करने के लिए स्वतंत्र महसूस करें। मैं समझता हूं कि आपका क्या मतलब है, लेकिन यकीन नहीं है कि बहुत सुधार हुआ है।
बबल बबल

117

आप रेगेक्स पुनरावर्तन का उपयोग कर सकते हैं :

\(([^()]|(?R))*\)

3
एक उदाहरण वास्तव में यहां उपयोगी होगा, मैं इसे "(1, (2, 3)) (4, 5)" जैसी चीजों के लिए काम नहीं कर सकता।
एंडी हेडन

4
@AndyHayden ऐसा इसलिए है क्योंकि "(1, (2, 3)) (4, 5)" दो समूह अंतरिक्ष के साथ अलग हो गए हैं। वैश्विक ध्वज के साथ मेरे regexp का उपयोग करें: / (([^ ()] | (? R)) *) / g यहाँ ऑनलाइन टेस्ट है: regex101.com/r/lF0fI1/1
rogal111

1
मैंने पिछले हफ्ते इस बारे में एक सवाल पूछा है stackoverflow.com/questions/26385984/recursive-pattern-in-regex
एंडी हेडन

7
.NET 4.5 में मुझे इस पैटर्न के लिए निम्न त्रुटि मिलती है Unrecognized grouping construct:।
नाम

3
बहुत बढ़िया! यह रेगेक्स की एक बड़ी विशेषता है। वास्तव में सवाल का जवाब देने के लिए केवल एक होने के लिए धन्यवाद। इसके अलावा, उस regex101 साइट मिठाई है।
एंड्रयू

28
[^\(]*(\(.*\))[^\)]*

[^\(]*स्ट्रिंग की शुरुआत में सब कुछ है कि एक खुलने वाले कोष्ठक से मेल नहीं खाता है (\(.*\)), कोष्ठक में संलग्न आवश्यक विकल्प को पकड़ता है, और [^\)]*वह सब कुछ मेल खाता है जो स्ट्रिंग के अंत में एक समापन कोष्ठक नहीं है। ध्यान दें कि यह अभिव्यक्ति कोष्ठक से मेल खाने का प्रयास नहीं करता है; एक साधारण पार्सर ( dehmann का उत्तर देखें ) उसके लिए अधिक उपयुक्त होगा।


वर्ग के अंदर के ब्रैकेट को भागने की जरूरत नहीं है। चूंकि यह अंदर नहीं है।
जोस लील

10
यह विस्तार "पाठ (पाठ) पाठ (पाठ)" पाठ "(पाठ) पाठ (पाठ)" जैसे कुछ के खिलाफ विफल रहता है। नियमित अभिव्यक्ति कोष्ठक की गिनती नहीं कर सकते हैं।
क्रिश्चियन क्लासर

17
(?<=\().*(?=\))

यदि आप दो मिलान वाले कोष्ठकों के बीच पाठ का चयन करना चाहते हैं, तो आप नियमित अभिव्यक्ति के साथ भाग्य से बाहर हैं। यह असंभव (*) है

यह रेग्जेस आपके स्ट्रिंग में पहले खुलने और अंतिम समापन कोष्ठक के बीच पाठ को लौटाता है।


(*) जब तक आपके रेगेक्स इंजन में संतुलन समूहों या पुनरावृत्ति जैसी विशेषताएं नहीं होती हैं । इस तरह की सुविधाओं का समर्थन करने वाले इंजनों की संख्या धीरे-धीरे बढ़ रही है, लेकिन वे अभी भी आमतौर पर उपलब्ध नहीं हैं।


"<=" और "=" संकेतों का क्या मतलब है? यह अभिव्यक्ति लक्ष्यीकरण क्या है?
क्रिश्चियन क्लासर

1
यह लुक-अराउंड, या अधिक सही ढंग से "शून्य चौड़ाई लुक-फ़ॉरवर्ड / लुक-बैक अस्सिटन्स" है। अधिकांश आधुनिक रेगेक्स इंजन उनका समर्थन करते हैं।
तोमलक

ओपी के उदाहरण के अनुसार, वह मैच में सबसे बाहरी पार्न्स को शामिल करना चाहता है। यह रेगेक्स उन्हें दूर फेंकता है।
एलन मूर

1
@ एलन एम: आप सही कह रहे हैं। लेकिन सवाल के पाठ के अनुसार, वह बाहरी सब कुछ के बीच सब कुछ चाहता है । अपनी पसंद चुनें। उन्होंने कहा कि वह घंटों से कोशिश कर रहे थे, इसलिए "सबसे बाहरी परगने सहित सब कुछ" को भी इरादे के रूप में नहीं माना, क्योंकि यह बहुत तुच्छ है: "(*। *)"।
तोमलक

3
@ghayes जवाब 2009 से है। यह एक लंबे समय से पहले है; नियमित अभिव्यक्ति इंजन जो कुछ प्रकार की पुनरावृत्ति की अनुमति देते हैं वे अब की तुलना में अधिक असामान्य हो गए हैं (और वे अभी भी बहुत असामान्य हैं)। मैं अपने उत्तर में इसका उल्लेख करूंगा।
तोमलक

14

यह उत्तर सैद्धांतिक सीमा की व्याख्या करता है कि क्यों नियमित अभिव्यक्ति इस कार्य के लिए सही उपकरण नहीं है।


नियमित अभिव्यक्ति ऐसा नहीं कर सकती।

नियमित अभिव्यक्तियाँ एक कंप्यूटिंग मॉडल पर आधारित होती हैं, जिसे जाना जाता है Finite State Automata (FSA)। जैसा कि नाम से संकेत मिलता है, FSAकेवल वर्तमान स्थिति को याद कर सकते हैं, यह पिछले राज्यों के बारे में कोई जानकारी नहीं है।

एफएसए

उपरोक्त आरेख में, एस 1 और एस 2 दो राज्य हैं जहां एस 1 शुरुआती और अंतिम चरण है। इसलिए यदि हम स्ट्रिंग के साथ प्रयास करते हैं 0110, तो संक्रमण निम्नानुसार है:

      0     1     1     0
-> S1 -> S2 -> S2 -> S2 ->S1

उपरोक्त चरणों में, जब हम दूसरे स्थान पर होते हैं, जब S2पार्स करने 01के बाद 0110, एफएसए को पहले के बारे में कोई जानकारी नहीं होती 0है 01क्योंकि यह केवल वर्तमान स्थिति और अगले इनपुट प्रतीक को याद कर सकता है।

उपरोक्त समस्या में, हमें कोष्ठक खोलने की कोई आवश्यकता नहीं है; इसका मतलब है कि इसे किसी स्थान पर संग्रहीत किया जाना है। लेकिन चूँकि FSAsऐसा नहीं किया जा सकता है, एक नियमित अभिव्यक्ति नहीं लिखी जा सकती है।

हालाँकि, इस कार्य को करने के लिए एक एल्गोरिथम लिखा जा सकता है। एल्गोरिदम आमतौर पर नीचे आते हैं Pushdown Automata (PDA)PDAके ऊपर एक स्तर है FSA। पीडीए के पास कुछ अतिरिक्त जानकारी संग्रहीत करने के लिए एक अतिरिक्त स्टैक है। पीडीए का उपयोग उपरोक्त समस्या को हल करने के लिए किया जा सकता है, क्योंकि हम pushस्टैक में खुलने वाले कोष्ठक को ' ' कर सकते हैं और ' pop' एक बार क्लोजिंग कोष्ठक का सामना करने के बाद उन्हें ' ' कर सकते हैं। यदि अंत में, स्टैक खाली है, तो कोष्ठक खोलना और कोष्ठक मिलान बंद करना है। नहीं तो नहीं।



1
यहाँ कई उत्तर हैं, जो प्रस्तावित करता है, यह संभव है।
जिनी हर्निक

1
@ मार्को यह उत्तर सैद्धांतिक परिप्रेक्ष्य में नियमित अभिव्यक्तियों के बारे में बात करता है। कई रेगेक्स इंजन अब एक दिन न केवल इस सैद्धांतिक मॉडल पर भरोसा करते हैं और काम करने के लिए कुछ अतिरिक्त मेमोरी का उपयोग करते हैं!
2

@ Ji @íHerník: वे सख्त अर्थों में नियमित अभिव्यक्ति नहीं हैं: क्लेन द्वारा नियमित अभिव्यक्ति के रूप में परिभाषित नहीं किया गया है । कुछ नियमित अभिव्यक्ति इंजनों ने वास्तव में कुछ अतिरिक्त क्षमताओं को लागू किया है, जिससे वे केवल नियमित भाषाओं से अधिक पार्स करते हैं
विलेम वान ओन्सेम

12

.NET रेगुलर एक्सप्रेशन का उपयोग करके वास्तव में ऐसा करना संभव है, लेकिन यह तुच्छ नहीं है, इसलिए ध्यान से पढ़ें।

आप यहाँ एक अच्छा लेख पढ़ सकते हैं । आपको .NET रेगुलर एक्सप्रेशन पर पढ़ना भी पड़ सकता है। आप यहां पढ़ना शुरू कर सकते हैं

कोण कोष्ठक <>का उपयोग किया गया था क्योंकि उन्हें भागने की आवश्यकता नहीं होती है।

नियमित अभिव्यक्ति इस तरह दिखाई देती है:

<
[^<>]*
(
    (
        (?<Open><)
        [^<>]*
    )+
    (
        (?<Close-Open>>)
        [^<>]*
    )+
)*
(?(Open)(?!))
>

4

यह निश्चित रीगेक्स है:

\(
(?<arguments> 
(  
  ([^\(\)']*) |  
  (\([^\(\)']*\)) |
  '(.*?)'

)*
)
\)

उदाहरण:

input: ( arg1, arg2, arg3, (arg4), '(pip' )

output: arg1, arg2, arg3, (arg4), '(pip'

ध्यान दें कि '(pip'स्ट्रिंग के रूप में सही ढंग से प्रबंधित किया गया है। (नियामक में कोशिश की: http://sourceforge.net/projects/regulator/ )


4

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

balanced.matches({
    source: source,
    open: '(',
    close: ')'
});

आप प्रतिस्थापन भी कर सकते हैं:

balanced.replacements({
    source: source,
    open: '(',
    close: ')',
    replace: function (source, head, tail) {
        return head + source + tail;
    }
});

यहां एक अधिक जटिल और इंटरैक्टिव उदाहरण JSFiddle है


4

बबल बबल के जवाब में जोड़कर , अन्य रेगेक्स फ्लेवर हैं जहां पुनरावर्ती निर्माण का समर्थन किया जाता है।

लुआ

का प्रयोग करें %b()( %b{}/ %b[]घुंघराले ब्रेसिज़ के लिए / वर्ग कोष्ठक):

  • for s in string.gmatch("Extract (a(b)c) and ((d)f(g))", "%b()") do print(s) end( डेमो देखें )

Perl6 :

गैर-अतिव्यापी कई संतुलित कोष्ठक मेल खाते हैं:

my regex paren_any { '(' ~ ')' [ <-[()]>+ || <&paren_any> ]* }
say "Extract (a(b)c) and ((d)f(g))" ~~ m:g/<&paren_any>/;
# => (「(a(b)c)」 「((d)f(g))」)

कई संतुलित कोष्ठकों के मिलान से अधिक:

say "Extract (a(b)c) and ((d)f(g))" ~~ m:ov:g/<&paren_any>/;
# => (「(a(b)c)」 「(b)」 「((d)f(g))」 「(d)」 「(g)」)

डेमो देखें ।

अजगर reगैर रेगेक्स समाधान

देखें प्रहार का जवाब के लिए कैसे संतुलित कोष्ठकों के बीच एक अभिव्यक्ति पाने के लिए

जावा अनुकूलन गैर-रेगेक्स समाधान

यहाँ जावा में एकल वर्ण शाब्दिक सीमांकक की अनुमति देने वाला अनुकूलन योग्य समाधान है:

public static List<String> getBalancedSubstrings(String s, Character markStart, 
                                 Character markEnd, Boolean includeMarkers) 

{
        List<String> subTreeList = new ArrayList<String>();
        int level = 0;
        int lastOpenDelimiter = -1;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (c == markStart) {
                level++;
                if (level == 1) {
                    lastOpenDelimiter = (includeMarkers ? i : i + 1);
                }
            }
            else if (c == markEnd) {
                if (level == 1) {
                    subTreeList.add(s.substring(lastOpenDelimiter, (includeMarkers ? i + 1 : i)));
                }
                if (level > 0) level--;
            }
        }
        return subTreeList;
    }
}

नमूना उपयोग:

String s = "some text(text here(possible text)text(possible text(more text)))end text";
List<String> balanced = getBalancedSubstrings(s, '(', ')', true);
System.out.println("Balanced substrings:\n" + balanced);
// => [(text here(possible text)text(possible text(more text)))]

एक प्रमाण के लिए एक ऑनलाइन जावा डेमो देखें यह कई मैचों के साथ काम करता है।
विकटोरिया स्ट्रीब्यूव


3

आपको पहले और आखिरी कोष्ठक की आवश्यकता है। कुछ इस तरह का उपयोग करें:

str.indexOf ('('); - यह आपको पहली घटना देगा

str.lastIndexOf ( ')'); - आखरी

तो आप के बीच एक स्ट्रिंग की जरूरत है,

String searchedString = str.substring(str1.indexOf('('),str1.lastIndexOf(')');

1
"""
Here is a simple python program showing how to use regular
expressions to write a paren-matching recursive parser.

This parser recognises items enclosed by parens, brackets,
braces and <> symbols, but is adaptable to any set of
open/close patterns.  This is where the re package greatly
assists in parsing. 
"""

import re


# The pattern below recognises a sequence consisting of:
#    1. Any characters not in the set of open/close strings.
#    2. One of the open/close strings.
#    3. The remainder of the string.
# 
# There is no reason the opening pattern can't be the
# same as the closing pattern, so quoted strings can
# be included.  However quotes are not ignored inside
# quotes.  More logic is needed for that....


pat = re.compile("""
    ( .*? )
    ( \( | \) | \[ | \] | \{ | \} | \< | \> |
                           \' | \" | BEGIN | END | $ )
    ( .* )
    """, re.X)

# The keys to the dictionary below are the opening strings,
# and the values are the corresponding closing strings.
# For example "(" is an opening string and ")" is its
# closing string.

matching = { "(" : ")",
             "[" : "]",
             "{" : "}",
             "<" : ">",
             '"' : '"',
             "'" : "'",
             "BEGIN" : "END" }

# The procedure below matches string s and returns a
# recursive list matching the nesting of the open/close
# patterns in s.

def matchnested(s, term=""):
    lst = []
    while True:
        m = pat.match(s)

        if m.group(1) != "":
            lst.append(m.group(1))

        if m.group(2) == term:
            return lst, m.group(3)

        if m.group(2) in matching:
            item, s = matchnested(m.group(3), matching[m.group(2)])
            lst.append(m.group(2))
            lst.append(item)
            lst.append(matching[m.group(2)])
        else:
            raise ValueError("After <<%s %s>> expected %s not %s" %
                             (lst, s, term, m.group(2)))

# Unit test.

if __name__ == "__main__":
    for s in ("simple string",
              """ "double quote" """,
              """ 'single quote' """,
              "one'two'three'four'five'six'seven",
              "one(two(three(four)five)six)seven",
              "one(two(three)four)five(six(seven)eight)nine",
              "one(two)three[four]five{six}seven<eight>nine",
              "one(two[three{four<five>six}seven]eight)nine",
              "oneBEGINtwo(threeBEGINfourENDfive)sixENDseven",
              "ERROR testing ((( mismatched ))] parens"):
        print "\ninput", s
        try:
            lst, s = matchnested(s)
            print "output", lst
        except ValueError as e:
            print str(e)
    print "done"

0

इसका उत्तर इस बात पर निर्भर करता है कि आपको कोष्ठक के मिलान सेट से मेल खाना है, या इनपुट पाठ में अंतिम बंद के लिए पहला खुला है।

यदि आपको मिलान किए गए नेस्टेड ब्रैकेट्स से मेल खाना है, तो आपको नियमित अभिव्यक्तियों से अधिक कुछ चाहिए। - देखें @ देहम

अगर यह सिर्फ पिछले बंद देखने के लिए पहले खुला है @Zach के

तय करें कि आप क्या करना चाहते हैं:

abc ( 123 ( foobar ) def ) xyz ) ghij

आपको यह तय करने की आवश्यकता है कि इस मामले में आपके कोड को क्या मेल खाना चाहिए।


3
यह कोई उत्तर नहीं है।
एलन मूर

हां, प्रश्न में बदलाव की मांग एक टिप्पणी के रूप में दी जानी चाहिए,
गंगनुस

0

क्योंकि js regex पुनरावर्ती मैच का समर्थन नहीं करता है, मैं संतुलित कोष्ठक मिलान कार्य नहीं कर सकता।

इसलिए यह लूप संस्करण के लिए एक सरल जावास्क्रिप्ट है जो सरणी में "विधि (arg)" स्ट्रिंग बनाता है

push(number) map(test(a(a()))) bass(wow, abc)
$$(groups) filter({ type: 'ORGANIZATION', isDisabled: { $ne: true } }) pickBy(_id, type) map(test()) as(groups)
const parser = str => {
  let ops = []
  let method, arg
  let isMethod = true
  let open = []

  for (const char of str) {
    // skip whitespace
    if (char === ' ') continue

    // append method or arg string
    if (char !== '(' && char !== ')') {
      if (isMethod) {
        (method ? (method += char) : (method = char))
      } else {
        (arg ? (arg += char) : (arg = char))
      }
    }

    if (char === '(') {
      // nested parenthesis should be a part of arg
      if (!isMethod) arg += char
      isMethod = false
      open.push(char)
    } else if (char === ')') {
      open.pop()
      // check end of arg
      if (open.length < 1) {
        isMethod = true
        ops.push({ method, arg })
        method = arg = undefined
      } else {
        arg += char
      }
    }
  }

  return ops
}

// const test = parser(`$$(groups) filter({ type: 'ORGANIZATION', isDisabled: { $ne: true } }) pickBy(_id, type) map(test()) as(groups)`)
const test = parser(`push(number) map(test(a(a()))) bass(wow, abc)`)

console.log(test)

परिणाम जैसा है

[ { method: 'push', arg: 'number' },
  { method: 'map', arg: 'test(a(a()))' },
  { method: 'bass', arg: 'wow,abc' } ]
[ { method: '$$', arg: 'groups' },
  { method: 'filter',
    arg: '{type:\'ORGANIZATION\',isDisabled:{$ne:true}}' },
  { method: 'pickBy', arg: '_id,type' },
  { method: 'map', arg: 'test()' },
  { method: 'as', arg: 'groups' } ]

0

जबकि इतने सारे उत्तर किसी न किसी रूप में यह कहते हुए उल्लेख करते हैं कि रेगेक्स पुनरावर्ती मिलान का समर्थन नहीं करता है और इसी तरह, इसका मुख्य कारण थ्योरी ऑफ़ कम्प्यूटेशन की जड़ों में निहित है।

रूप की भाषा {a^nb^n | n>=0} is not regular। रेगेक्स केवल उन चीजों से मेल खा सकता है जो भाषाओं के नियमित सेट का हिस्सा हैं।

और अधिक पढ़ें @ यहाँ


0

मैंने regex का उपयोग नहीं किया क्योंकि यह नेस्टेड कोड से निपटना मुश्किल है। तो यह स्निपेट आपको संतुलित कोष्ठक के साथ कोड के वर्गों को हथियाने की अनुमति देने में सक्षम होना चाहिए:

def extract_code(data):
    """ returns an array of code snippets from a string (data)"""
    start_pos = None
    end_pos = None
    count_open = 0
    count_close = 0
    code_snippets = []
    for i,v in enumerate(data):
        if v =='{':
            count_open+=1
            if not start_pos:
                start_pos= i
        if v=='}':
            count_close +=1
            if count_open == count_close and not end_pos:
                end_pos = i+1
        if start_pos and end_pos:
            code_snippets.append((start_pos,end_pos))
            start_pos = None
            end_pos = None

    return code_snippets

मैंने इसका इस्तेमाल टेक्स्ट फाइल से कोड स्निपेट्स निकालने के लिए किया था।


0

मैं इस स्थिति में भी फंस गया था जहां नेस्टेड पैटर्न आते हैं।

उपरोक्त समस्या को हल करने के लिए नियमित अभिव्यक्ति सही बात है। नीचे पैटर्न का उपयोग करें

'/(\((?>[^()]+|(?1))*\))/'


-1

यह कुछ के लिए उपयोगी हो सकता है:

जावास्क्रिप्ट में फ़ंक्शन स्ट्रिंग (नेस्टेड संरचनाओं के साथ) से पार्समीटर

मैच संरचनाओं की तरह:
फ़ंक्शन स्ट्रिंग से पार्समीटर

  • कोष्ठक, वर्ग कोष्ठक, कोष्ठक, एकल और दोहरे उद्धरणों से मेल खाता है

यहां आप कार्रवाई में उत्पन्न रेगेक्स को देख सकते हैं

/**
 * get param content of function string.
 * only params string should be provided without parentheses
 * WORK even if some/all params are not set
 * @return [param1, param2, param3]
 */
exports.getParamsSAFE = (str, nbParams = 3) => {
    const nextParamReg = /^\s*((?:(?:['"([{](?:[^'"()[\]{}]*?|['"([{](?:[^'"()[\]{}]*?|['"([{][^'"()[\]{}]*?['")}\]])*?['")}\]])*?['")}\]])|[^,])*?)\s*(?:,|$)/;
    const params = [];
    while (str.length) { // this is to avoid a BIG performance issue in javascript regexp engine
        str = str.replace(nextParamReg, (full, p1) => {
            params.push(p1);
            return '';
        });
    }
    return params;
};

यह पूरी तरह से ओपी प्रश्न को संबोधित नहीं करता है, लेकिन मैं नेस्टेड संरचना regexp की खोज करने के लिए यहां आने वाले कुछ लोगों के लिए उपयोगी हो सकता है।

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