मुझे दो बाहरी कोष्ठक के बीच सभी पाठ का चयन करने के लिए एक नियमित अभिव्यक्ति की आवश्यकता है।
उदाहरण: some text(text here(possible text)text(possible text(more text)))end text
परिणाम: (text here(possible text)text(possible text(more text)))
मुझे दो बाहरी कोष्ठक के बीच सभी पाठ का चयन करने के लिए एक नियमित अभिव्यक्ति की आवश्यकता है।
उदाहरण: some text(text here(possible text)text(possible text(more text)))end text
परिणाम: (text here(possible text)text(possible text(more text)))
जवाबों:
नियमित अभिव्यक्ति नौकरी के लिए गलत उपकरण है क्योंकि आप नेस्टेड संरचनाओं के साथ काम कर रहे हैं, अर्थात पुनरावृत्ति।
लेकिन वहाँ यह करने के लिए एक सरल एल्गोरिथ्म, जो मैं वर्णित है इस जवाब में एक करने के लिए पिछले प्रश्न ।
मैं इस जवाब को त्वरितता के लिए जोड़ना चाहता हूं। अद्यतन करने के लिए स्वतंत्र महसूस करें।
.NET बैलेंसिंग समूहों का उपयोग करके रेगेक्स ।
\((?>\((?<c>)|[^()]+|\)(?<-c>))*(?(c)(?!))\)
जहां cगहराई काउंटर के रूप में उपयोग किया जाता है।
एक पुनरावर्ती पैटर्न का उपयोग कर पीसीआरई ।
\((?:[^)(]+|(?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 पर डेमो करें । डीपर नेस्टिंग को पैटर्न में जोड़ने की जरूरत है ।
असंतुलित कोष्ठक पर तेजी से विफल करने के लिए लिए +मात्रा को गिरा दें ।
जावा : @ संजय द्वारा आगे के संदर्भों का उपयोग करते हुए एक दिलचस्प विचार ।
(?>[^)(]+|(?R))*+की तुलना में एक ही है (?:[^)(]+|(?R))*+। अगले पैटर्न के लिए एक ही बात। अनियंत्रित संस्करण के बारे में, आप यहां एक प्रभावशाली मात्रा निर्धारित कर सकते हैं: [^)(]*+बैकट्रैकिंग को रोकने के लिए (यदि कोई समापन ब्रैकेट नहीं है)।
(...(..)..(..)..(..)..(..)..)विषय स्ट्रिंग में)), तो आपको एक परमाणु समूह में सभी संलग्न एक सरल गैर पर कब्जा समूह का उपयोग कर सकते हैं और: (?>(?:[^)(]+|\g<1>)*)( यह एक अधिकारपूर्ण मात्रात्मक की तरह व्यवहार करता है)। रूबी 2.x में, प्रथक क्वांटिफायर उपलब्ध है।
आप रेगेक्स पुनरावर्तन का उपयोग कर सकते हैं :
\(([^()]|(?R))*\)
Unrecognized grouping construct:।
[^\(]*(\(.*\))[^\)]*
[^\(]*स्ट्रिंग की शुरुआत में सब कुछ है कि एक खुलने वाले कोष्ठक से मेल नहीं खाता है (\(.*\)), कोष्ठक में संलग्न आवश्यक विकल्प को पकड़ता है, और [^\)]*वह सब कुछ मेल खाता है जो स्ट्रिंग के अंत में एक समापन कोष्ठक नहीं है। ध्यान दें कि यह अभिव्यक्ति कोष्ठक से मेल खाने का प्रयास नहीं करता है; एक साधारण पार्सर ( dehmann का उत्तर देखें ) उसके लिए अधिक उपयुक्त होगा।
(?<=\().*(?=\))
यदि आप दो मिलान वाले कोष्ठकों के बीच पाठ का चयन करना चाहते हैं, तो आप नियमित अभिव्यक्ति के साथ भाग्य से बाहर हैं। यह असंभव (*) है ।
यह रेग्जेस आपके स्ट्रिंग में पहले खुलने और अंतिम समापन कोष्ठक के बीच पाठ को लौटाता है।
(*) जब तक आपके रेगेक्स इंजन में संतुलन समूहों या पुनरावृत्ति जैसी विशेषताएं नहीं होती हैं । इस तरह की सुविधाओं का समर्थन करने वाले इंजनों की संख्या धीरे-धीरे बढ़ रही है, लेकिन वे अभी भी आमतौर पर उपलब्ध नहीं हैं।
यह उत्तर सैद्धांतिक सीमा की व्याख्या करता है कि क्यों नियमित अभिव्यक्ति इस कार्य के लिए सही उपकरण नहीं है।
नियमित अभिव्यक्ति ऐसा नहीं कर सकती।
नियमित अभिव्यक्तियाँ एक कंप्यूटिंग मॉडल पर आधारित होती हैं, जिसे जाना जाता है 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' एक बार क्लोजिंग कोष्ठक का सामना करने के बाद उन्हें ' ' कर सकते हैं। यदि अंत में, स्टैक खाली है, तो कोष्ठक खोलना और कोष्ठक मिलान बंद करना है। नहीं तो नहीं।
.NET रेगुलर एक्सप्रेशन का उपयोग करके वास्तव में ऐसा करना संभव है, लेकिन यह तुच्छ नहीं है, इसलिए ध्यान से पढ़ें।
आप यहाँ एक अच्छा लेख पढ़ सकते हैं । आपको .NET रेगुलर एक्सप्रेशन पर पढ़ना भी पड़ सकता है। आप यहां पढ़ना शुरू कर सकते हैं ।
कोण कोष्ठक <>का उपयोग किया गया था क्योंकि उन्हें भागने की आवश्यकता नहीं होती है।
नियमित अभिव्यक्ति इस तरह दिखाई देती है:
<
[^<>]*
(
(
(?<Open><)
[^<>]*
)+
(
(?<Close-Open>>)
[^<>]*
)+
)*
(?(Open)(?!))
>
यह निश्चित रीगेक्स है:
\(
(?<arguments>
(
([^\(\)']*) |
(\([^\(\)']*\)) |
'(.*?)'
)*
)
\)
उदाहरण:
input: ( arg1, arg2, arg3, (arg4), '(pip' )
output: arg1, arg2, arg3, (arg4), '(pip'
ध्यान दें कि '(pip'स्ट्रिंग के रूप में सही ढंग से प्रबंधित किया गया है। (नियामक में कोशिश की: http://sourceforge.net/projects/regulator/ )
मैंने इस काम में मदद के लिए एक छोटी सी जावास्क्रिप्ट लाइब्रेरी लिखी है, जिसे संतुलित किया गया है। आप इसे करके पूरा कर सकते हैं
balanced.matches({
source: source,
open: '(',
close: ')'
});
आप प्रतिस्थापन भी कर सकते हैं:
balanced.replacements({
source: source,
open: '(',
close: ')',
replace: function (source, head, tail) {
return head + source + tail;
}
});
यहां एक अधिक जटिल और इंटरैक्टिव उदाहरण JSFiddle है ।
बबल बबल के जवाब में जोड़कर , अन्य रेगेक्स फ्लेवर हैं जहां पुनरावर्ती निर्माण का समर्थन किया जाता है।
लुआ
का प्रयोग करें %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)))]
रूबी (संस्करण 1.9.3 या इसके बाद के संस्करण) का उपयोग करते हुए नियमित अभिव्यक्ति:
/(?<match>\((?:\g<match>|[^()]++)*\))/
"""
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"
इसका उत्तर इस बात पर निर्भर करता है कि आपको कोष्ठक के मिलान सेट से मेल खाना है, या इनपुट पाठ में अंतिम बंद के लिए पहला खुला है।
यदि आपको मिलान किए गए नेस्टेड ब्रैकेट्स से मेल खाना है, तो आपको नियमित अभिव्यक्तियों से अधिक कुछ चाहिए। - देखें @ देहम
अगर यह सिर्फ पिछले बंद देखने के लिए पहले खुला है @Zach के
तय करें कि आप क्या करना चाहते हैं:
abc ( 123 ( foobar ) def ) xyz ) ghij
आपको यह तय करने की आवश्यकता है कि इस मामले में आपके कोड को क्या मेल खाना चाहिए।
क्योंकि 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' } ]
जबकि इतने सारे उत्तर किसी न किसी रूप में यह कहते हुए उल्लेख करते हैं कि रेगेक्स पुनरावर्ती मिलान का समर्थन नहीं करता है और इसी तरह, इसका मुख्य कारण थ्योरी ऑफ़ कम्प्यूटेशन की जड़ों में निहित है।
रूप की भाषा {a^nb^n | n>=0} is not regular। रेगेक्स केवल उन चीजों से मेल खा सकता है जो भाषाओं के नियमित सेट का हिस्सा हैं।
और अधिक पढ़ें @ यहाँ
मैंने 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
मैंने इसका इस्तेमाल टेक्स्ट फाइल से कोड स्निपेट्स निकालने के लिए किया था।
यह एक भी काम किया
re.findall(r'\(.+\)', s)
यह कुछ के लिए उपयोगी हो सकता है:
यहां आप कार्रवाई में उत्पन्न रेगेक्स को देख सकते हैं
/**
* 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 की खोज करने के लिए यहां आने वाले कुछ लोगों के लिए उपयोगी हो सकता है।