আমি যতদূর জানি, ভারসাম্যপূর্ণ গোষ্ঠীগুলি .NET এর রেগেক্স স্বাদে অনন্য।
পাশে: পুনরাবৃত্তি গোষ্ঠী
প্রথমত, আপনার জানা দরকার যে নেট। (আবার, যতদূর আমি জানি) একমাত্র রেইগেক্স গন্ধ যা আপনাকে একক ক্যাপচারিং গ্রুপের একাধিক ক্যাপচারগুলি অ্যাক্সেস করতে দেয় (ব্যাকরফারেন্সে নয় তবে ম্যাচটি শেষ হওয়ার পরে)।
একটি উদাহরণ দিয়ে উদাহরণস্বরূপ, প্যাটার্ন বিবেচনা করুন
(.)+
এবং স্ট্রিং "abcd"।
অন্যান্য সমস্ত রেগেক্স স্বাদে, ক্যাপচারিং গ্রুপটি 1কেবল একটি ফল দেবে: d(দ্রষ্টব্য, পুরো ম্যাচটি অবশ্যই abcdপ্রত্যাশা মতো হবে)। এটি কারণ ক্যাপচারিং গ্রুপের প্রতিটি নতুন ব্যবহার পূর্ববর্তী ক্যাপচারকে ওভাররাইট করে।
.NET অন্যদিকে তাদের সকলের স্মরণ করে। এবং এটি স্ট্যাকের মধ্যে তাই করে। উপরের রেজেক্সের সাথে মিলের পরে লাইক দিন
Match m = new Regex(@"(.)+").Match("abcd");
আপনি এটি পাবেন
m.Groups[1].Captures
এমন একটি CaptureCollectionযা এর উপাদানগুলি চারটি ক্যাপচারের সাথে মিলে যায়
0: "a"
1: "b"
2: "c"
3: "d"
যেখানে নম্বরটি সূচক CaptureCollection। সুতরাং মূলত প্রতিবার এই গ্রুপটি ব্যবহার করা হলে, নতুন ক্যাপচারটি স্ট্যাকের দিকে ঠেলে দেওয়া হয়।
যদি আমরা নামকৃত ক্যাপচারিং গ্রুপগুলি ব্যবহার করি তবে এটি আরও আকর্ষণীয় হয়ে ওঠে। কারণ .NET একই নামটির পুনরাবৃত্তি ব্যবহারের অনুমতি দেয় যা আমরা পছন্দ করে একটি রেইজেক্স লিখতে পারি
(?<word>\w+)\W+(?<word>\w+)
একই গ্রুপে দুটি শব্দ ক্যাপচার। আবার, যখনই কোনও নির্দিষ্ট নামের একটি গোষ্ঠী মুখোমুখি হয়, তখন একটি স্ট্যাকের উপরে একটি ক্যাপচার চাপানো হয়। সুতরাং ইনপুটটিতে এই রেজেক্স প্রয়োগ করে "foo bar"এবং পরিদর্শন করা হচ্ছে
m.Groups["word"].Captures
আমরা দুটি ক্যাপচার খুঁজে
0: "foo"
1: "bar"
এটি আমাদেরকে এমনকি ভাবের বিভিন্ন অংশ থেকে একক স্ট্যাকের মধ্যে জিনিসগুলি ধাক্কা দিতে দেয়। কিন্তু তবুও, এটি কেবল নেট। এর তালিকাভুক্ত একাধিক ক্যাপচার ট্র্যাক করতে সক্ষম হওয়ার বৈশিষ্ট্য CaptureCollection। তবে আমি বলেছিলাম, এই সংগ্রহটি একটি স্ট্যাক । সুতরাং আমরা কি এটি থেকে জিনিসগুলি পপ করতে পারি ?
প্রবেশ করুন: ব্যালান্সিং গ্রুপগুলি
এটি আমরা করতে পারি। যদি আমরা এর মতো একটি গোষ্ঠী ব্যবহার করি তবে স্যুটপ্রেসশন মেলে যদি (?<-word>...)শেষ ক্যাপচারটি স্ট্যাক থেকে পপ করা হয় । সুতরাং আমরা যদি আমাদের পূর্বের অভিব্যক্তিটি পরিবর্তন করিword...
(?<word>\w+)\W+(?<-word>\w+)
তারপরে দ্বিতীয় গোষ্ঠীটি প্রথম গ্রুপের ক্যাপচারটি পপ করবে এবং আমরা CaptureCollectionশেষ পর্যন্ত একটি খালি পেয়ে যাব । অবশ্যই, এই উদাহরণটি বেশ অকেজো।
তবে বিয়োগ-সিনট্যাক্সের আরও একটি বিশদ রয়েছে: যদি স্ট্যাকটি ইতিমধ্যে খালি থাকে তবে গোষ্ঠীটি ব্যর্থ হয় (তার সাবপ্যাটার্ন নির্বিশেষে)। নেস্টিংয়ের স্তরগুলি গণনা করার জন্য আমরা এই আচরণটি কাজে লাগাতে পারি - এবং এটিই নামটি ভারসাম্যপূর্ণ গ্রুপ থেকে আসে (এবং এটি আকর্ষণীয় হয়ে ওঠে)। বলুন আমরা সঠিকভাবে প্রথম বন্ধনীযুক্ত স্ট্রিংগুলি মেলতে চাই। আমরা প্রতিটি খোলার প্রথম বন্ধনীকে স্ট্যাকের উপরে চাপি এবং প্রতিটি বন্ধ হওয়া বন্ধনীগুলির জন্য একটি ক্যাপচারকে পপ করি। যদি আমরা একটি ক্লোজিং বন্ধনী খুব বেশি মুখোমুখি হয় তবে এটি একটি খালি স্ট্যাক পপ করার চেষ্টা করবে এবং প্যাটার্নটি ব্যর্থ হওয়ার কারণ হবে:
^(?:[^()]|(?<Open>[(])|(?<-Open>[)]))*$
সুতরাং একটি পুনরাবৃত্তি আমাদের তিনটি বিকল্প আছে। প্রথম বিকল্পটি প্যারেনেসিস নয় এমন সমস্ত কিছু গ্রাস করে। দ্বিতীয় বিকল্প ম্যাচগুলি (স্ট্যাকের দিকে ধাক্কা দেওয়ার সময়। )স্ট্যাক থেকে উপাদান পপ করার সময় তৃতীয় বিকল্প মেলে (যদি সম্ভব হয়!)।
দ্রষ্টব্য: কেবল স্পষ্ট করার জন্য, আমরা কেবল এটি যাচাই করছি যে কোনও মিল নেই! এর অর্থ এই যে সব সময়ে কোন প্রথম বন্ধনী ধারণকারী স্ট্রিং হবে , মেলে কারণ তারা এখনও চিহ্নগুলি সিন্টেক্সের বৈধ (কিছু সিনট্যাক্স যেখানে আপনি মিলটির আপনার প্রথম বন্ধনী প্রয়োজন)। আপনি যদি কমপক্ষে একটি বন্ধনীগুলির একটি সেট নিশ্চিত করতে চান তবে কেবল এর (?=.*[(])পরে ডানদিকে একটি চেহারা যুক্ত করুন ^।
যদিও এই নিদর্শনটি নিখুঁত নয় (বা সম্পূর্ণ সঠিক)।
সমাপ্তি: শর্তাধীন প্যাটার্নস
আরও একটি ধরা আছে: এটি স্ট্রিংয়ের শেষে স্ট্যাকটি খালি রয়েছে তা নিশ্চিত করে না (সুতরাং (foo(bar)এটি বৈধ হবে)। । নেট (এবং অন্যান্য স্বাদযুক্ত) এর মধ্যে আরও একটি নির্মাণ রয়েছে যা আমাদের এখানে সহায়তা করে: শর্তাধীন নিদর্শন। সাধারণ বাক্য গঠনটি হ'ল
(?(condition)truePattern|falsePattern)
যেখানে falsePatternoptionচ্ছিক - এটি বাদ দিলে মিথ্যা মামলা সর্বদা মিলবে। শর্তটি হয় কোনও প্যাটার্ন বা ক্যাপচারিং গোষ্ঠীর নাম হতে পারে। আমি এখানে উত্তরোত্তর ক্ষেত্রে ফোকাস করব। যদি এটি কোনও ক্যাপচারিং গোষ্ঠীর নাম হয়, তবে truePatternসেই নির্দিষ্ট গ্রুপের ক্যাপচার স্ট্যাকটি খালি না হলেই ব্যবহৃত হয়। এটি হ'ল শর্তসাপেক্ষ প্যাটার্ন যেমন (?(name)yes|no)"যদি কোনও nameকিছু মিলে যায় এবং ক্যাপচার করে থাকে (এটি এখনও স্ট্যাকের মধ্যে রয়েছে), প্যাটার্নটি yesঅন্যথায় প্যাটার্নটি ব্যবহার করুন no"।
সুতরাং আমাদের উপরের প্যাটার্নটির শেষে আমরা এমন কিছু যুক্ত করতে পারি (?(Open)failPattern)যা পুরো প্যাটার্নটি ব্যর্থ করে দেয়, যদি Openস্ট্যাকটি খালি না থাকে। (?!)নিদর্শনকে নিঃশর্ত ব্যর্থ করার সহজ জিনিস হ'ল (একটি খালি নেতিবাচক চেহারা)। সুতরাং আমরা আমাদের চূড়ান্ত প্যাটার্ন আছে:
^(?:[^()]|(?<Open>[(])|(?<-Open>[)]))*(?(Open)(?!))$
নোট করুন যে এই শর্তসাপেক্ষ বাক্য গঠনটি ভারসাম্যপূর্ণ গ্রুপগুলির সাথে করার জন্য কিছুই নেই তবে তাদের পূর্ণ শক্তি প্রয়োগ করা প্রয়োজন।
এখান থেকে আকাশ সীমাবদ্ধ। অনেক অত্যন্ত পরিশীলিত ব্যবহার সম্ভব এবং অন্যান্য .NET-Regex বৈশিষ্ট্য যেমন ভেরিয়েবল-দৈর্ঘ্যের বর্ণনক্ষেত্রগুলির ( যা আমাকে নিজের মতো করে নিজেই শিখতে হয়েছিল ) এর সাথে সংমিশ্রণে ব্যবহার করা হয় তখন কিছু গ্যাটাচ রয়েছে । তবে মূল প্রশ্নটি সর্বদা: এই বৈশিষ্ট্যগুলি ব্যবহার করার পরে আপনার কোডটি কি এখনও বজায় রাখা যায়? আপনার এটি সত্যই ভাল নথিভুক্ত করা প্রয়োজন, এবং নিশ্চিত হয়ে নিন যে এতে কাজ করা প্রত্যেকে এই বৈশিষ্ট্যগুলি সম্পর্কে অবগত আছেন। অন্যথায় আপনি আরও ভাল হতে পারেন, কেবল স্ট্রিং ম্যানুয়ালি অক্ষর দ্বারা অক্ষর এবং একটি পূর্ণসংখ্যার নেস্টিং স্তর গণনা।
সংযোজন: (?<A-B>...)সিনট্যাক্সের সাথে কী ?
এই অংশের ক্রেডিটগুলি কোবিতে যান (আরও তথ্যের জন্য নীচে তার উত্তর দেখুন)।
উপরের সমস্তটির সাথে এখন, আমরা যাচাই করতে পারি যে একটি স্ট্রিং সঠিকভাবে প্রথম বন্ধনী হয়েছে। তবে এটি অনেক বেশি কার্যকর হবে, যদি আমরা সেই সমস্ত প্রথম বন্ধনী সামগ্রীর জন্য বাস্তবে (নেস্টেড) ক্যাপচার পেতে পারি। অবশ্যই, আমরা খালি নয় এমন একটি পৃথক ক্যাপচার স্ট্যাকের বন্ধনীগুলি খোলার এবং বন্ধ করার কথা মনে করতে পারি এবং তারপরে একটি পৃথক পদক্ষেপে তাদের অবস্থানের উপর ভিত্তি করে কিছু স্ট্রস্ট্রিং নিষ্কাশন করতে পারি।
কিন্তু। নেট এখানে এখানে আরও একটি সুবিধার বৈশিষ্ট্য সরবরাহ করে: আমরা যদি এটি ব্যবহার করি তবে (?<A-B>subPattern)কেবল স্ট্যাক থেকে ক্যাপচারই Bনয়, সেই পপড ক্যাপচার Bএবং এই বর্তমান গ্রুপের মধ্যে থাকা সমস্ত কিছুকে স্ট্যাকের দিকে ঠেলা দেওয়া হচ্ছে A। সুতরাং আমরা যদি স্ট্যাক থেকে বাসা বাঁধার সময় বন্ধ করার বন্ধনীগুলির জন্য এই জাতীয় একটি গোষ্ঠী ব্যবহার করি, আমরা জোড়ের সামগ্রীটি অন্য স্ট্যাকের দিকেও চাপ দিতে পারি:
^(?:[^()]|(?<Open>[(])|(?<Content-Open>[)]))*(?(Open)(?!))$
কোবি তার উত্তরে এই লাইভ- ডেমোটি সরবরাহ করেছিলেন
সুতরাং এই সমস্ত জিনিস একসাথে আমরা নিতে পারি:
- ইচ্ছামত অনেক ক্যাপচার মনে রাখবেন
- নেস্টেড স্ট্রাকচারগুলি বৈধ করুন
- নীড়ের প্রতিটি স্তর ক্যাপচার করুন
সব একক নিয়মিত প্রকাশে expression যদি তা উত্তেজনাপূর্ণ না হয় ...;)
আমি যখন সেগুলি সম্পর্কে প্রথম জানতে পেরেছিলাম তখন কিছু সংস্থানগুলি সহায়তা পেয়েছিল: