दिलचस्प पोस्ट
कैसे WinDbg में प्रतीकों को सेट करने के लिए? यदि विभिन्न तत्व हैं तो क्या कई अलग-अलग HTML तत्वों की समान आईडी हो सकती है? अपने डीटीडी या एक्सएसडी से नमूना XML दस्तावेज़ कैसे तैयार करें? पायथन में टाइम ज़ोन संक्षिप्त नाम के साथ दिनांक / समय स्ट्रिंग पार्स करना? IOS 10 में UITextView के शीर्ष पर रिक्त स्थान Android में ListView आइटम निकालें कैसे अक्षम कॉपी, कट, चुनें, सभी का चयन करें UITextView में एक UIScrollView में स्क्रॉलिंग की दिशा खोजना? सत्र खोने का राज्य क्यों सी + कंटेनरों अधूरा प्रकार की अनुमति नहीं देते? क्लाइंट-साइड और सर्वर-साइड प्रोग्रामिंग के बीच अंतर क्या है? अपरिवर्तनीय से क्या मतलब है? वर्तमान निष्पादन विधि का नाम प्राप्त करना एक्शन बार पर टेक्स्ट कैसे बदल सकता है अभिगम नियंत्रण-अनुमति-उत्पत्ति द्वारा उत्पत्ति की अनुमति नहीं है

पायथन: रेगेक्स के साथ नेस्टेड कोष्ठक से मिलान कैसे करें?

मैं एक गणितीय-अभिव्यक्ति-जैसी स्ट्रिंग से मिलान करने की कोशिश कर रहा हूं, जो नेस्टेड कोष्ठक है

import re p = re.compile('\(.+\)') str = '(((1+0)+1)+1)' print p.findall(s) 

[ '(((1 + 0) +1) +1)]

मैं इसे सभी संलग्न भावों से मिलान करना चाहता था, जैसे कि (1 + 0), ((1 + 0) +1) …
मुझे तब भी परवाह नहीं है अगर यह अवांछित लोगों से मेल खाती है (((1 + 0), मैं उनकी देखभाल कर सकता हूं

यह पहले से ही ऐसा क्यों नहीं कर रहा है, और मैं यह कैसे कर सकता हूं?

वेब के समाधान से एकत्रित समाधान "पायथन: रेगेक्स के साथ नेस्टेड कोष्ठक से मिलान कैसे करें?"

नियमित अभिव्यक्ति जितनी संभव हो उतनी पाठ को मैच करने की कोशिश करती है, जिससे आपके सभी स्ट्रिंग का उपभोग हो जाता है यह उस स्ट्रिंग के कुछ हिस्सों पर नियमित अभिव्यक्ति के अतिरिक्त मिलानों की खोज नहीं करता है। यही कारण है कि आपको केवल एक ही जवाब मिलता है।

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

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

 import pyparsing # make sure you have this installed thecontent = pyparsing.Word(pyparsing.alphanums) | '+' | '-' parens = pyparsing.nestedExpr( '(', ')', content=thecontent) 

यहां एक उपयोग उदाहरण है:

 >>> parens.parseString("((a + b) + c)") 

आउटपुट:

 ( # all of str [ ( # ((a + b) + c) [ ( # (a + b) ['a', '+', 'b'], {} ), # (a + b) [closed] '+', 'c' ], {} ) # ((a + b) + c) [closed] ], {} ) # all of str [closed] 

(नईलाइनिंग / इंडेंटिंग / मैन्युअल रूप से टिप्पणियां)

संपादित करें: पॉल McGuire के सुझावों के अनुसार, अनावश्यक अग्रेषण को खत्म करने के लिए संशोधित

नेस्टेड सूची प्रारूप में आउटपुट प्राप्त करने के लिए:

 res = parens.parseString("((12 + 2) + 3)") res.asList() 

आउटपुट:

 [[['12', '+', '2'], '+', '3']] 

मौजूदा एक को अजगर में बदलने के लिए एक नया नियमित इंजन मॉड्यूल तैयार किया जा रहा है। यह रिकर्सिव कॉल्स सहित कई नई कार्यक्षमता का परिचय देता है।

 import regex s = 'aaa(((1+0)+1)+1)bbb' result = regex.search(r''' (?<rec> #capturing group rec \( #open parenthesis (?: #non-capturing group [^()]++ #anyting but parenthesis one or more times without backtracking | #or (?&rec) #recursive substitute of group rec )* \) #close parenthesis ) ''',s,flags=regex.VERBOSE) print(result.captures('rec')) 

आउटपुट:

 ['(1+0)', '((1+0)+1)', '(((1+0)+1)+1)'] 

regex में संबंधित बग: http://code.google.com/p/mrab-regex-hg/issues/detail?id=78

रेगेक्स भाषाओं मनमाने ढंग से नेस्टेड निर्माणों के मिलान के लिए पर्याप्त शक्तिशाली नहीं हैं। इसके लिए आपको एक पुश-डाउन ऑटमॉन (यानी, एक पार्सर) की आवश्यकता है। ऐसे कई उपकरण उपलब्ध हैं, जैसे कि PLY

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

 >>> import parser, pprint >>> pprint.pprint(parser.st2list(parser.expr('(((1+0)+1)+1)'))) [258, [327, [304, [305, [306, [307, [308, [310, [311, [312, [313, [314, [315, [316, [317, [318, [7, '('], [320, [304, [305, [306, [307, [308, [310, [311, [312, [313, [314, [315, [316, [317, [318, [7, '('], [320, [304, [305, [306, [307, [308, [310, [311, [312, [313, [314, [315, [316, [317, [318, [7, '('], [320, [304, [305, [306, [307, [308, [310, [311, [312, [313, [314, [315, [316, [317, [318, [2, '1']]]]], [14, '+'], [315, [316, [317, [318, [2, '0']]]]]]]]]]]]]]]], [8, ')']]]]], [14, '+'], [315, [316, [317, [318, [2, '1']]]]]]]]]]]]]]]], [8, ')']]]]], [14, '+'], [315, [316, [317, [318, [2, '1']]]]]]]]]]]]]]]], [8, ')']]]]]]]]]]]]]]]], [4, ''], [0, '']] 

आप इस लघु समारोह के साथ दर्द को कम कर सकते हैं:

 def shallow(ast): if not isinstance(ast, list): return ast if len(ast) == 2: return shallow(ast[1]) return [ast[0]] + [shallow(a) for a in ast[1:]] >>> pprint.pprint(shallow(parser.st2list(parser.expr('(((1+0)+1)+1)')))) [258, [318, '(', [314, [318, '(', [314, [318, '(', [314, '1', '+', '0'], ')'], '+', '1'], ')'], '+', '1'], ')'], '', ''] 

संख्या पायथन मॉड्यूल symbol और token से आती है, जिसका उपयोग आप संख्याओं से नामों के लिए एक लुकअप तालिका बनाने के लिए कर सकते हैं:

 map = dict(token.tok_name.items() + symbol.sym_name.items()) 

आप इस मैपिंग को shallow() फ़ंक्शन में भी गुना कर सकते हैं ताकि आप संख्याओं के बजाय तार के साथ काम कर सकें:

 def shallow(ast): if not isinstance(ast, list): return ast if len(ast) == 2: return shallow(ast[1]) return [map[ast[0]]] + [shallow(a) for a in ast[1:]] >>> pprint.pprint(shallow(parser.st2list(parser.expr('(((1+0)+1)+1)')))) ['eval_input', ['atom', '(', ['arith_expr', ['atom', '(', ['arith_expr', ['atom', '(', ['arith_expr', '1', '+', '0'], ')'], '+', '1'], ')'], '+', '1'], ')'], '', ''] 

कार्य के लिए स्टैक सबसे अच्छा उपकरण है: –

 import re def matches(line, opendelim='(', closedelim=')'): stack = [] for m in re.finditer(r'[{}{}]'.format(opendelim, closedelim), line): pos = m.start() if line[pos-1] == '\\': # skip escape sequence continue c = line[pos] if c == opendelim: stack.append(pos+1) elif c == closedelim: if len(stack) > 0: prevpos = stack.pop() # print("matched", prevpos, pos, line[prevpos:pos]) yield (prevpos, pos, len(stack)) else: # error print("encountered extraneous closing quote at pos {}: '{}'".format(pos, line[pos:] )) pass if len(stack) > 0: for pos in stack: print("expecting closing quote to match open quote starting at: '{}'" .format(line[pos-1:])) 

क्लाइंट कोड में, चूंकि फ़ंक्शन को जनरेटर फ़ंक्शन के रूप में लिखा जाता है, तो मैचों को खोलने के लिए केवल लूप पैटर्न का उपयोग करें: –

 line = '(((1+0)+1)+1)' for openpos, closepos, level in matches(line): print(line[openpos:closepos], level) 

यह परीक्षण कोड मेरी स्क्रीन पर निम्नलिखित का उत्पादन करता है, देखा कि प्रिंटआउट में दूसरे परम कोष्ठक की गहराई को इंगित करता है।

 1+0 2 (1+0)+1 1 ((1+0)+1)+1 0 

जुड़े उत्तर से:

लिलपोंड कन्वर्ट-ली उपयोगिता (और खुद / द्वारा लिखित / कॉपीराइट किया गया है, इसलिए मैं इसे यहां दिखा सकता हूं):

 def paren_matcher (n): # poor man's matched paren scanning, gives up # after n+1 levels. Matches any string with balanced # parens inside; add the outer parens yourself if needed. # Nongreedy. return r"[^()]*?(?:\("*n+r"[^()]*?"+r"\)[^()]*?)*?"*n 

कन्वर्ट-लिइन को इसके नियमित अभिव्यक्ति में क्रास_मैचर (25) के रूप में उपयोग करने की आदत होती है, जो कि अधिकांश अनुप्रयोगों के लिए ओवरकिल हो सकता है। लेकिन फिर यह योजना अभिव्यक्तियों के मिलान के लिए इसका उपयोग करता है।

हां, यह दी गई सीमा के बाद टूट जाती है, लेकिन यह नियमित अभिव्यक्तियों में प्लग करने की क्षमता अभी भी "सही" विकल्पों को असीमित गहराई का समर्थन करता है, जो प्रयोज्यता में हाथों से नीचे होती है।

बैलेंस्ड जोड़े (कोष्ठक के, उदाहरण के लिए) एक ऐसी भाषा का उदाहरण है जिसे नियमित अभिव्यक्तियों द्वारा पहचाना नहीं जा सकता।

इसके बाद गणित का एक संक्षिप्त विवरण इस प्रकार है कि यह क्यों है

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

उदाहरण के लिए, राज्य को गिनती के लिए इस्तेमाल किया जा सकता है, कहते हैं, बेमिसाल बाएं कोष्ठक। लेकिन क्योंकि उस तरह की गिनती के लिए राज्य की मात्रा पूरी तरह से घिरी हुई हो, तो एक दिया गया एफएसएम अधिकतम एन -1 तक भरोसा कर सकता है, जहां एन एफएसएम के राज्यों की संख्या है। यदि n है, कहते हैं, 10 , तब तक अधिकतम संख्या में छोड़े गए बाएं कोष्ठक के साथ एफएसएम मैच 10 हो सकता है, जब तक कि यह टूट नहीं सकता। चूंकि यह एक और छोड़े गए कोष्ठक के लिए पूरी तरह से संभव है, इसलिए संभव नहीं FSM जो मिलानित कोष्ठकों की पूरी भाषा को सही ढंग से पहचान सकता है।

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

तुलना करके, भाषाओं के अगले बेहतर वर्ग (संदर्भ मुक्त व्याकरण) इस समस्या को पूरी तरह से कॉम्पैक्ट तरीके से हल कर सकते हैं। यहां बीएनएफ में एक उदाहरण है

expression ::= ` ( ` expression ` ) ` expression
| nothing

आपको ऐसी अभिव्यक्ति पार्स करने के लिए एक उचित पार्सर लिखना चाहिए (उदाहरण के लिए पाइपरिंग का प्रयोग करना) सभ्य पार्सर लिखने के लिए नियमित अभिव्यक्ति कोई उपयुक्त उपकरण नहीं हैं।

आप regexps का उपयोग कर सकते हैं, लेकिन आपको स्वतः ही पुनरावर्ती करने की आवश्यकता है निम्नलिखित की तरह कुछ चाल है (यदि आपको केवल खोजने की जरूरत है, आपका प्रश्न कहता है, तो सभी अभिव्यक्तिएं कोष्ठक में संलग्न किया गया है):

 import re def scan(p, string): found = p.findall(string) for substring in found: stripped = substring[1:-1] found.extend(scan(p, stripped)) return found p = re.compile('\(.+\)') string = '(((1+0)+1)+1)' all_found = scan(p, string) print all_found 

यह कोड, हालांकि, 'सही' कोष्ठक से मेल नहीं खाता। अगर आपको ऐसा करने की आवश्यकता है तो आप एक विशिष्ट पार्सर के साथ बेहतर हो जाएंगे

मेरा मानना ​​है कि यह फ़ंक्शन आपकी ज़रूरतों को पूरा कर सकता है, मैंने इसे एक साथ तेजी से फेंक दिया, इसलिए इसे थोड़ा साफ करने के लिए बेझिझक। जब घोंसले को पीछे की ओर सोचने और वहां से काम करना आसान होता है =]

 def fn(string,endparens=False): exp = [] idx = -1 for char in string: if char == "(": idx += 1 exp.append("") elif char == ")": idx -= 1 if idx != -1: exp[idx] = "(" + exp[idx+1] + ")" else: exp[idx] += char if endparens: exp = ["("+val+")" for val in exp] return exp 

कई पदों ने सुझाव दिया है कि नेस्टेड ब्रेसिज़ के लिए, रीगएक्स यह करने का तरीका नहीं है I सीधा संख्याएं ब्रैक्स: उदाहरण के लिए, देखें: अर्ध-बृहदान्त्र का पता लगाने के लिए नियमित अभिव्यक्ति सी ++ और लूप के लिए समाप्त होती है

स्ट्रिंग के माध्यम से पुनरावृत्त करने के लिए यहां एक पूर्ण अजगर नमूना है और ब्रेसों को गिनें:

 # decided for nested braces to not use regex but brace-counting import re, string texta = r''' nonexistent.\note{Richard Dawkins, \textit{Unweaving the Rainbow: Science, Delusion and the Appetite for Wonder} (Boston: Houghton Mifflin Co., 1998), pp. 302, 304, 306-309.} more text and more. This is a statistical fact, not a guess.\note{Zheng Wu, \textit{Cohabitation: An Alternative Form of Family Living} (Ontario, Canada: Oxford University Press, 2000), p. 149; \hbox{Judith} Treas and Deirdre Giesen, ``Title and another title,'' \textit{Journal of Marriage and the Family}, February 2000, p.\,51} more and more text.capitalize ''' pos = 0 foundpos = 0 openBr = 0 # count open braces while foundpos <> -1: openBr = 0 foundpos = string.find(texta, r'\note',pos) # print 'foundpos',foundpos pos = foundpos + 5 # print texta[pos] result = "" while foundpos > -1 and openBr >= 0: pos = pos + 1 if texta[pos] == "{": openBr = openBr + 1 if texta[pos] == "}": openBr = openBr - 1 result = result + texta[pos] result = result[:-1] # drop the last } found. result = string.replace(result,'\n', ' ') # replace new line with space print result