দুটি বাইরের বন্ধনীগুলির মধ্যে সমস্ত পাঠ্য নির্বাচন করতে আমার একটি নিয়মিত প্রকাশ দরকার need
উদাহরণ: some text(text here(possible text)text(possible text(more text)))end text
ফলাফল: (text here(possible text)text(possible text(more text)))
দুটি বাইরের বন্ধনীগুলির মধ্যে সমস্ত পাঠ্য নির্বাচন করতে আমার একটি নিয়মিত প্রকাশ দরকার need
উদাহরণ: 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)
।
পার্ল, পিএইচপি, নোটপ্যাড ++, আর : পার্ল = সত্য , পাইথন : রেজেক্স প্যাকেজ সঙ্গে (?V1)
পার্ল আচরণের জন্য।
রুবি ব্যবহার করেসুবি এক্সপ্রেসন কল ।
রুবি ২.০ সহ \g<0>
সম্পূর্ণ প্যাটার্ন কল করতে ব্যবহার করা যেতে পারে।
\((?>[^)(]+|\g<0>)*\)
রুবুলারে ডেমো ; রুবি ১.৯ কেবলমাত্র গ্রুপ পুনরুক্তি ক্যাপচার সমর্থন করে :
(\((?>[^)(]+|\g<1>)*\))
রুবুলারে ডেমো ( পারমাণবিক গ্রুপিং) রুবি ১.৯.৩ থেকে )
জাভাস্ক্রিপ্ট API: XRegExp.matchRecursive
XRegExp.matchRecursive(str, '\\(', '\\)', 'g');
জেএস, জাভা এবং অন্যান্য রেজেক্স স্বাদগুলি নীড়ের 2 স্তর পর্যন্ত পুনরাবৃত্তি ছাড়াই:
\((?:[^)(]+|\((?:[^)(]+|\([^)(]*\))*\))*\)
Regex101 এ ডেমো । নিখরচায় আরও গভীর বাসা বাঁধতে হবে ।
ভারসাম্যহীন প্রথম বন্ধনে দ্রুত ব্যর্থ হওয়ার জন্য +
কোয়ান্টিফায়ারটি ড্রপ করুন ।
জাভা : ফরোয়ার্ড রেফারেন্সগুলি @ জেটিয়া ব্যবহার করে একটি আকর্ষণীয় ধারণা ।
(?>[^)(]+|(?R))*+
চেয়ে লেখাই সমান (?:[^)(]+|(?R))*+
। পরের প্যাটার্নের জন্য একই জিনিস। অনিবন্ধিত সংস্করণ সম্পর্কে, আপনি এখানে একটি অধিকারী পরিমাণ [^)(]*+
রাখতে পারেন: ব্যাকট্র্যাকিং রোধ করতে (কোনও বন্ধনী বন্ধনী না থাকলে ক্ষেত্রে)।
(...(..)..(..)..(..)..(..)..)
সাবজেক্ট স্ট্রিংয়ে পুনরাবৃত্তি হওয়া গ্রুপটিকে পারমাণবিক (যেখানে অনেক নেস্টেড প্যারেনেসিস রয়েছে তার সীমিত আগ্রহ রয়েছে ) পরিবর্তে, আপনি একটি সাধারণ অ-ক্যাপচারিং গ্রুপ ব্যবহার করতে পারেন এবং সমস্তকে একটি পারমাণবিক গ্রুপে সংযুক্ত করতে পারেন: (?>(?:[^)(]+|\g<1>)*)
( এটি হ'ল একটি অধিকারী কোয়ান্টিফায়ারের মতো আচরণ করে)। রুবি ২.x-এ, অধিকারী কোয়ান্টিফায়ার উপলব্ধ।
আপনি রেজেক্স পুনরাবৃত্তি ব্যবহার করতে পারেন :
\(([^()]|(?R))*\)
Unrecognized grouping construct
।
[^\(]*(\(.*\))[^\)]*
[^\(]*
স্ট্রিংয়ের শুরুতে খোলার ব্র্যাকেট নয় এমন সমস্ত কিছুর সাথে মেলে (\(.*\))
, বন্ধনীগুলিতে আবদ্ধ প্রয়োজনীয় স্ট্রিংগুলি ক্যাপচার করে এবং [^\)]*
স্ট্রিংয়ের শেষে বন্ধ হওয়া বন্ধনী নয় এমন সমস্ত কিছু মেলে। নোট করুন যে এই অভিব্যক্তিটি বন্ধনীগুলির সাথে মিলের চেষ্টা করে না; একটি সাধারণ পার্সার ( দেহমানের উত্তর দেখুন ) এর জন্য আরও উপযুক্ত হবে।
(?<=\().*(?=\))
আপনি যদি দুটি ম্যাচিংয়ের প্রথম বন্ধনীর মধ্যে পাঠ্য নির্বাচন করতে চান , আপনি নিয়মিত প্রকাশের সাথে ভাগ্যের বাইরে। এটি অসম্ভব (*) ।
এই রেজেক্সটি আপনার স্ট্রিংয়ের প্রথম প্রারম্ভিক এবং শেষ বন্ধক প্রথম বন্ধনের মধ্যবর্তী পাঠ্যটি কেবল ফেরত দেয়।
(*) আপনার Regex ইঞ্জিন যদি মত বৈশিষ্ট্য আছে মিট গ্রুপ বা পুনরাবৃত্তির । এই জাতীয় বৈশিষ্ট্যগুলিকে সমর্থন করে এমন ইঞ্জিনগুলির সংখ্যা ধীরে ধীরে বৃদ্ধি পাচ্ছে, তবে এগুলি এখনও সাধারণভাবে পাওয়া যায় না।
এই উত্তরটি কেন এই কাজের জন্য নিয়মিত প্রকাশগুলি সঠিক সরঞ্জাম নয় তার তাত্ত্বিক সীমাবদ্ধতার ব্যাখ্যা দেয়।
নিয়মিত প্রকাশগুলি এটি করতে পারে না।
নিয়মিত এক্সপ্রেশন হিসাবে পরিচিত একটি কম্পিউটিং মডেল উপর ভিত্তি করে 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
' একবার আমরা যখন ক্লোজিং বন্ধনীর মুখোমুখি হই। যদি শেষে, স্ট্যাক খালি থাকে, তবে বন্ধনী খোলা এবং বন্ধনীর প্রথম ম্যাচ বন্ধ করুন। অন্যথায় না।
নেট নিয়মিত এক্সপ্রেশন ব্যবহার করে এটি করা সম্ভব, তবে এটি তুচ্ছ নয়, তাই মনোযোগ দিয়ে পড়ুন।
আপনি এখানে একটি সুন্দর নিবন্ধ পড়তে পারেন । আপনার নেট। নিয়মিত প্রকাশ করতে হবে read আপনি এখানে পড়া শুরু করতে পারেন ।
অ্যাঙ্গেল বন্ধনী <>
ব্যবহার করা হয়েছিল কারণ তাদের পালানোর প্রয়োজন নেই।
নিয়মিত অভিব্যক্তিটি এরকম দেখাচ্ছে:
<
[^<>]*
(
(
(?<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;
}
});
এখানে আরও জটিল এবং ইন্টারেক্টিভ উদাহরণ জেএসফিডাল ।
বুদবুদ বুবলীর উত্তরে যুক্ত করা হচ্ছে , এমন আরও রেইগেক্স স্বাদ রয়েছে যেখানে পুনরাবৃত্ত কনস্ট্রাক্টস সমর্থিত।
অ্যাপ্লিকেশন Lua
ব্যবহারের %b()
( %b{}
/ %b[]
কোঁকড়া ধনুর্বন্ধনী জন্য / বর্গাকার বন্ধনী):
for s in string.gmatch("Extract (a(b)c) and ((d)f(g))", "%b()") do print(s) end
( ডেমো দেখুন )পার্ল 6 :
অ-ওভারল্যাপিং একাধিক ভারসাম্য প্রথম বন্ধনী মেলে:
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"
উত্তরটি ব্র্যাকেটের মিলের সেটগুলির সাথে মিলানোর প্রয়োজন কিনা, বা ইনপুট পাঠ্যের কেবল সর্বশেষে প্রথম উন্মুক্ত হওয়া উচিত তার উপর নির্ভর করে।
যদি আপনাকে নেস্টেড বন্ধনীগুলির সাথে ম্যাচিং করতে হয় তবে আপনার নিয়মিত প্রকাশের চেয়ে আরও বেশি কিছু প্রয়োজন। - দেখুন @ ডিহম্যান
যদি এটি কেবল প্রথম উন্মুক্ত হয় তবে শেষ দেখুন @ জ্যাচ
আপনি কী হতে চান তা স্থির করুন:
abc ( 123 ( foobar ) def ) xyz ) ghij
এই ক্ষেত্রে আপনার কোডটি কী মিলবে তা আপনাকে সিদ্ধান্ত নিতে হবে।
যেহেতু জেএস রেজেেক্স পুনরাবৃত্তির ম্যাচ সমর্থন করে না, আমি ভারসাম্যপূর্ণ বন্ধনী ম্যাচিং কাজ করতে পারি না।
সুতরাং এটি লুপ সংস্করণের জন্য একটি সহজ জাভাস্ক্রিপ্ট যা "পদ্ধতি (আরগ)" স্ট্রিংকে অ্যারে করে তোলে
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' } ]
যদিও এতগুলি উত্তর একরকম আকারে এটি উল্লেখ করে রেগেক্স পুনরাবৃত্ত মিলে যাওয়া সমর্থন করে না ইত্যাদি, এটির প্রাথমিক কারণটি থিওরি অফ কম্পিউটেশনের মূলের মধ্যে রয়েছে lies
ফর্মের ভাষা {a^nb^n | n>=0} is not regular
। রেগেক্স কেবলমাত্র সেই ভাষাগুলির সাথে মেলে যা ভাষার নিয়মিত সেটগুলির অংশ হয়ে যায়।
আরও এখানে পড়ুন
নেস্টেড কোডগুলি মোকাবেলা করা কঠিন হওয়ার কারণে আমি রেজেক্স ব্যবহার করিনি। সুতরাং এই স্নিপেটটি আপনাকে ভারসাম্য বন্ধনীর সাথে কোডের কিছু অংশ দখল করতে সক্ষম হতে হবে:
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;
};
এটি ওপি প্রশ্নের সম্পূর্ণরূপে সম্বোধন করে না তবে আমি নীস্ট স্ট্রাকচার রিজেক্সএক্স অনুসন্ধান করতে এখানে আসার কিছু লোকের পক্ষে এটি কার্যকর হতে পারে।