.NET নিয়মিত প্রকাশে "গোষ্ঠী" এবং "ক্যাপচার" এর মধ্যে পার্থক্য কী?


161

.NET- র নিয়মিত অভিব্যক্তি ভাষাটি যখন আসে তখন একটি "গোষ্ঠী" এবং "ক্যাপচার" এর মধ্যে পার্থক্য কী তা নিয়ে আমি কিছুটা অস্পষ্ট। নিম্নলিখিত সি # কোড বিবেচনা করুন:

MatchCollection matches = Regex.Matches("{Q}", @"^\{([A-Z])\}$");

আমি প্রত্যাশা করি যে এটি 'কিউ' অক্ষরটির জন্য একটি একক ক্যাপচারের ফলস্বরূপ, তবে আমি যদি ফিরে আসাগুলির সম্পত্তিগুলি মুদ্রণ করি তবে MatchCollectionআমি দেখতে পাচ্ছি:

matches.Count: 1
matches[0].Value: {Q}
        matches[0].Captures.Count: 1
                matches[0].Captures[0].Value: {Q}
        matches[0].Groups.Count: 2
                matches[0].Groups[0].Value: {Q}
                matches[0].Groups[0].Captures.Count: 1
                        matches[0].Groups[0].Captures[0].Value: {Q}
                matches[0].Groups[1].Value: Q
                matches[0].Groups[1].Captures.Count: 1
                        matches[0].Groups[1].Captures[0].Value: Q

এখানে ঠিক কি হচ্ছে? আমি বুঝতে পারি পুরো ম্যাচের জন্য একটি ক্যাপচার রয়েছে, তবে গ্রুপগুলি কীভাবে আসবে? এবং কেন matches[0].Captures'Q' অক্ষরের জন্য ক্যাপচারটি অন্তর্ভুক্ত করে না ?

উত্তর:


126

আপনি এটির সম্পর্কে অস্পষ্ট প্রথম নন। বিখ্যাত জেফ্রি ফ্রেডল এর সম্পর্কে যা বলতে চান তা এখানে (পৃষ্ঠা 437+):

আপনার দৃষ্টিভঙ্গির উপর নির্ভর করে এটি হয় ম্যাচের ফলাফলগুলিতে একটি আকর্ষণীয় নতুন মাত্রা যুক্ত করে, বা বিভ্রান্তি এবং ফোলাভাব যুক্ত করে।

এবং আরও:

একটি গ্রুপ অবজেক্ট এবং ক্যাপচার অবজেক্টের মধ্যে প্রধান পার্থক্য হ'ল প্রতিটি গ্রুপ অবজেক্টে ম্যাচের সময় গ্রুপের মধ্যস্থতাকারী সমস্ত ম্যাচের প্রতিনিধিত্বকারী ক্যাপচারের সংকলন এবং সেই সাথে গ্রুপের সাথে মিলিত চূড়ান্ত পাঠ থাকে।

এবং কয়েক পৃষ্ঠা পরে, এটি তাঁর উপসংহার:

.NET ডকুমেন্টেশনটি পাস করার পরে এবং এই বিষয়গুলি কী যুক্ত করে তা আসলে বুঝতে পেরে আমি তাদের সম্পর্কে মিশ্র অনুভূতি পেয়েছি। অন্যদিকে, এটি একটি আকর্ষণীয় উদ্ভাবন [..] অন্যদিকে, এটি কার্যকারিতাটির দক্ষতার বোঝা যুক্ত করছে বলে মনে হচ্ছে [..] যা বেশিরভাগ ক্ষেত্রে ব্যবহার করা হবে না

অন্য কথায়: এগুলি খুব সাদৃশ্যপূর্ণ তবে মাঝে মধ্যে এবং যেমনটি ঘটে, আপনি তাদের জন্য একটি ব্যবহার খুঁজে পাবেন। আপনি আরও ধূসর দাড়ি বাড়ার আগে আপনি ক্যাপচারগুলিও পছন্দ করতে পারেন ...


যেহেতু উপরের, বা অন্য পোস্টে যা বলা হয়েছে তা সত্যই আপনার প্রশ্নের উত্তর বলে মনে হচ্ছে না, তাই নিম্নলিখিতগুলি বিবেচনা করুন। ক্যাপচারগুলি এক ধরণের ইতিহাসের ট্র্যাকার হিসাবে ভাবেন। যখন রেজেক্স তার ম্যাচটি তৈরি করে, এটি বাম থেকে ডানে ডানদিকে চলে যায় (এক মুহুর্তের জন্য ব্যাকট্র্যাকিং উপেক্ষা করে) এবং যখন এটি কোনও ম্যাচিং ক্যাপচারিং প্রথম বন্ধনীর মুখোমুখি হয়, তখন এটি বলা যায় যে $x(কোনও সংখ্যার সাথে থাকা), আসুন $1

সাধারণ রেজেক্স ইঞ্জিনগুলি যখন ক্যাপচারিং প্রথম বন্ধনীর পুনরাবৃত্তি করা হয় তখন বর্তমানটি ফেলে $1দেবে এবং এটিকে নতুন মান দিয়ে প্রতিস্থাপন করবে। নেট নয়, যা এই ইতিহাস রাখবে এবং এতে রাখবে Captures[0]

আমরা যদি আপনার রেজেক্সকে নীচের মত দেখতে পরিবর্তন করি:

MatchCollection matches = Regex.Matches("{Q}{R}{S}", @"(\{[A-Z]\})+");

আপনি লক্ষ্য করবেন যে প্রথমটির একটি Groupহবে Captures(প্রথম গ্রুপটি সর্বদা পুরো ম্যাচ, অর্থাৎ সমান $0) এবং দ্বিতীয় গ্রুপটি হ'ল {S}, কেবলমাত্র সর্বশেষ ম্যাচিং গ্রুপ। যাইহোক, এবং এখানে ধরা আছে, আপনি যদি অন্য দুটি ক্যাচ খুঁজতে চান তবে সেগুলিতে Capturesরয়েছে, যার মধ্যে {Q} {R}এবং এর জন্য সমস্ত মধ্যস্থতাকারী ক্যাপচার রয়েছে {S}

আপনি যদি কখনও ভেবে থাকেন যে আপনি একাধিক-ক্যাপচার থেকে কীভাবে পেতে পারেন, যা কেবল স্ট্রিংয়ের মধ্যে পরিষ্কারভাবে থাকা ব্যক্তিগত ক্যাপচারগুলির সাথে শেষ ম্যাচটি দেখায়, আপনাকে অবশ্যই ব্যবহার করতে হবে Captures

আপনার চূড়ান্ত প্রশ্নের একটি চূড়ান্ত শব্দ: মোট ম্যাচে সর্বদা একটি মোট ক্যাপচার থাকে, এটি পৃথক গোষ্ঠীগুলির সাথে মিশ্রণ করবেন না। ক্যাপচারগুলি কেবলমাত্র গ্রুপগুলির মধ্যে আকর্ষণীয়


1
a functionality that won't be used in the majority of casesআমার মনে হয় সে নৌকাটি মিস করেছে। স্বল্পমেয়াদে (?:.*?(collection info)){4,20}দক্ষতা আরও কয়েকশ শতাংশ বেড়ে যায়।

1
@ এসএলএন, আপনি কী উল্লেখ করছেন এবং 'তিনি' কে (ফ্রিডেল?) নিশ্চিত হন না। আপনি যে উদাহরণটি দিয়েছেন তা এই আলোচনার সাথে বা ব্যবহৃত অভিব্যক্তির সাথে সম্পর্কিত নয় বলে মনে হচ্ছে। তদাতিরিক্ত, লোভী কোয়ান্টিফায়ার লোভী কোয়ানটিফায়ারগুলির চেয়ে খুব কমই বেশি দক্ষ এবং এর জন্য ইনপুট সেট এবং যত্নবান পারফ পরীক্ষার জ্ঞান প্রয়োজন require
আবেল

@ আবেল - আমি এটির একটি প্রশ্নের চিহ্নিত চিহ্ন থেকে এখানে অবতরণ করেছি। আমি ফ্রেডকে উদ্ধৃত দেখি। এই পোস্টটি পুরানো এবং এটি আধুনিক রাখার জন্য সতেজ করা দরকার। শুধুমাত্র ডট নেট দিয়ে এটি করা যায়, এটি এটি অন্যদের থেকে পৃথক। ভাঙ্গন: একটি পরিমাণযুক্ত নন-ক্যাপচার সামগ্রিক গ্রুপ উদাহরণ (?:..)+। অলসতার .*?সাথে কোনও ক্যাপচার সাব এক্সপ্রেশন (গোষ্ঠী) পর্যন্ত কোনও কিছুর সাথে মেলে । অবিরত. একটি একক ম্যাচের মধ্যে একটি গ্রুপ সংগ্রহ কেবলমাত্র যা প্রয়োজন তার একটি অ্যারেকে পূর্বরূপ দেয়। এরপরের সন্ধানের দরকার নেই, পুনরায় প্রবেশপথ নেই যা এটিকে 10 থেকে 20 বা আরও বেশি বার দ্রুত করে তোলে।

1
@ এসএলএন, এই প্রশ্নটি অন্য কোনও কিছুর বিষয়ে এবং এটি বিশেষত একটি এনট বৈশিষ্ট্য সম্পর্কে যা অন্য রেজেক্স ইঞ্জিনগুলিতে পাওয়া যায় না (গ্রুপ বনাম ক্যাপচার, শিরোনাম দেখুন)। আমি এখানে পুরানো কিছু দেখতে পাচ্ছি না। নেট এখনও একইভাবে কাজ করছে, প্রকৃতপক্ষে। নেট-এ এই অংশটি খুব বেশি সময় বদলেনি। পারফরম্যান্স প্রশ্নের অংশ নয়। হ্যাঁ, নন ক্যাপচারিং গ্রুপিং দ্রুত, তবে আবার এখানে বিষয়টি বিপরীত। লোভী কেন অলসতার চেয়ে দ্রুত, অনেকগুলি গ্রন্থে অনলাইনে এবং ফ্রেডেলের বই দ্বারা ব্যাখ্যা করা হয়েছে, তবে ওটি এখানে। হতে পারে অন্য প্রশ্নটি (কোনটি) সত্যিকারের সদৃশ ছিল না?
আবেল

2
@ আবেল - আমি জানি আমি এটি বলতে থাকি, তবে আপনি এটি শুনছেন না। ফ্রিডেলের এই বক্তব্যকে আমি ছাতা নিচ্ছি a functionality that won't be used in the majority of cases। প্রকৃতপক্ষে এটি রেজেক্স জমিগুলিতে সর্বাধিক চাওয়া হয়। অলস / লোভী? আমার মন্তব্যের সাথে এর কী সম্পর্ক? এটি ক্যাপচার বাফারগুলির একটি চলক পরিমাণে সক্ষম করে। এটি একক ম্যাচে পুরো স্ট্রিং স্যুইপ করতে পারে। তাহলে .*?(dog)খুঁজে বের করে প্রথম dogতারপর (?:.*?(dog))+পাবেন সব dog একটি একক ম্যাচে সমগ্র স্ট্রিং। কর্মক্ষমতা বৃদ্ধি লক্ষণীয়।

20

একটি গ্রুপ হ'ল আমরা নিয়মিত অভিব্যক্তিতে গ্রুপগুলির সাথে যুক্ত হয়েছি

"(a[zx](b?))"

Applied to "axb" returns an array of 3 groups:

group 0: axb, the entire match.
group 1: axb, the first group matched.
group 2: b, the second group matched.

এগুলি কেবল 'বন্দী' গ্রুপ are নন ক্যাপচারিং গ্রুপগুলি (':?' সিনট্যাক্স ব্যবহার করে এখানে উপস্থাপন করা হয় না।

"(a[zx](?:b?))"

Applied to "axb" returns an array of 2 groups:

group 0: axb, the entire match.
group 1: axb, the first group matched.

ক্যাপচার হ'ল আমরা 'বন্দী গোষ্ঠীগুলির' সাথে যা করেছি। কিন্তু যখন গ্রুপটি একাধিকবার কোয়ান্টিফায়ার দিয়ে প্রয়োগ করা হয়, কেবল শেষ ম্যাচটি গ্রুপের ম্যাচ হিসাবে রাখা হয়। ক্যাপচারগুলি অ্যারেটিকে এই সমস্ত ম্যাচ সঞ্চয় করে।

"(a[zx]\s+)+"

Applied to "ax az ax" returns an array of 2 captures of the second group.

group 1, capture 0 "ax "
group 1, capture 1 "az "

আপনার শেষ প্রশ্নটি হিসাবে - আমি এটি অনুসন্ধান করার আগে ভাবতাম যে ক্যাপচারগুলি তাদের সাথে সম্পর্কিত গ্রুপ দ্বারা অর্পিত ক্যাপচারগুলির একটি অ্যারে হবে। বরং এটি গোষ্ঠীগুলির জন্য কেবলমাত্র একটি উপনাম [0] C খুব অকেজো ..


পরিষ্কার ব্যাখ্যা (y)
ঘাসান

19

এটি একটি সাধারণ উদাহরণ (এবং ছবি) দিয়ে ব্যাখ্যা করা যেতে পারে।

3:10pmনিয়মিত প্রকাশের সাথে মিল ((\d)+):((\d)+)(am|pm), এবং মনো ইন্টারেক্টিভ ব্যবহার csharp:

csharp> Regex.Match("3:10pm", @"((\d)+):((\d)+)(am|pm)").
      > Groups.Cast<Group>().
      > Zip(Enumerable.Range(0, int.MaxValue), (g, n) => "[" + n + "] " + g);
{ "[0] 3:10pm", "[1] 3", "[2] 3", "[3] 10", "[4] 0", "[5] pm" }

তাহলে কোথায় 1? এখানে চিত্র বর্ণনা লিখুন

যেহেতু চতুর্থ গ্রুপের সাথে একাধিক সংখ্যা মেলে, তাই আমরা কেবলমাত্র শেষ ম্যাচটি "এ" পেতে পারি যদি আমরা গ্রুপটি উল্লেখ করি (একটি অন্তর্নিহিত সহ ToString(), এটি হয়)। মধ্যবর্তী ম্যাচগুলি উন্মোচিত করার জন্য, আমাদের আরও গভীরভাবে যেতে হবে Capturesএবং প্রশ্নে গ্রুপটিতে থাকা সম্পত্তিটি উল্লেখ করতে হবে :

csharp> Regex.Match("3:10pm", @"((\d)+):((\d)+)(am|pm)").
      > Groups.Cast<Group>().
      > Skip(4).First().Captures.Cast<Capture>().
      > Zip(Enumerable.Range(0, int.MaxValue), (c, n) => "["+n+"] " + c);
{ "[0] 1", "[1] 0" }

এখানে চিত্র বর্ণনা লিখুন

এই নিবন্ধ সৌজন্যে ।


3
চমৎকার নিবন্ধ। একটি ছবি হাজার শব্দের সমান.
অ্যালেক্সওয়ে

আপনি একজন তারকা.
মাইকমে

14

এমএসডিএন ডকুমেন্টেশন থেকে :

ক্যাপচার সম্পত্তিটির প্রকৃত ইউটিলিটিটি ঘটে যখন কোনও ক্যাপটিফায়ার একটি ক্যাপচারিং গ্রুপে প্রয়োগ করা হয় যাতে গোষ্ঠীটি একক নিয়মিত অভিব্যক্তিতে একাধিক সাবস্ট্রিংগুলি ক্যাপচার করে। এই ক্ষেত্রে, গ্রুপ অবজেক্টটিতে সর্বশেষ ক্যাপচার করা সাবস্ট্রিং সম্পর্কিত তথ্য রয়েছে, তবে ক্যাপচার সম্পত্তিটিতে গোষ্ঠী দ্বারা ক্যাপচারিত সমস্ত সাবস্ট্রিং সম্পর্কিত তথ্য রয়েছে। নিম্নলিখিত উদাহরণে নিয়মিত প্রকাশ \ b (\ w + \ s *) +। একটি সম্পূর্ণ বাক্যের সাথে মেলে যা একটি পিরিয়ডে শেষ হয়। গোষ্ঠী (\ w + \ s *) + সংগ্রহের পৃথক শব্দকে ধারণ করে। যেহেতু গ্রুপ সংগ্রহে কেবল সর্বশেষ গৃহীত সাবস্ট্রিং সম্পর্কিত তথ্য রয়েছে, এটি "বাক্য" বাক্যটিতে সর্বশেষ শব্দটি ধারণ করে। যাইহোক, গ্রুপ দ্বারা ক্যাপচার প্রতিটি শব্দ ক্যাপচার সম্পত্তি দ্বারা ফেরত সংগ্রহ থেকে পাওয়া যায় is


4

আপনার নীচের পাঠ্য ইনপুট dogcatcatcatএবং একটি প্যাটার্ন রয়েছে তা কল্পনা করুনdog(cat(catcat))

এই ক্ষেত্রে, আপনার 3 টি গ্রুপ রয়েছে, প্রথমটি ( বড় গ্রুপ) ) ম্যাচের সাথে মিলে যায়।

ম্যাচ == dogcatcatcatএবং গ্রুপ 0 ==dogcatcatcat

গ্রুপ 1 == catcatcat

গ্রুপ 2 == catcat

তাহলে এ সব কিসের?

আসুন Regexক্লাস ব্যবহার করে সি # (.NET) এ লিখিত একটি সামান্য উদাহরণ বিবেচনা করুন ।

int matchIndex = 0;
int groupIndex = 0;
int captureIndex = 0;

foreach (Match match in Regex.Matches(
        "dogcatabcdefghidogcatkjlmnopqr", // input
        @"(dog(cat(...)(...)(...)))") // pattern
)
{
    Console.Out.WriteLine($"match{matchIndex++} = {match}");

    foreach (Group @group in match.Groups)
    {
        Console.Out.WriteLine($"\tgroup{groupIndex++} = {@group}");

        foreach (Capture capture in @group.Captures)
        {
            Console.Out.WriteLine($"\t\tcapture{captureIndex++} = {capture}");
        }

        captureIndex = 0;
    }

    groupIndex = 0;
    Console.Out.WriteLine();
        }

আউটপুট :

match0 = dogcatabcdefghi
    group0 = dogcatabcdefghi
        capture0 = dogcatabcdefghi
    group1 = dogcatabcdefghi
        capture0 = dogcatabcdefghi
    group2 = catabcdefghi
        capture0 = catabcdefghi
    group3 = abc
        capture0 = abc
    group4 = def
        capture0 = def
    group5 = ghi
        capture0 = ghi

match1 = dogcatkjlmnopqr
    group0 = dogcatkjlmnopqr
        capture0 = dogcatkjlmnopqr
    group1 = dogcatkjlmnopqr
        capture0 = dogcatkjlmnopqr
    group2 = catkjlmnopqr
        capture0 = catkjlmnopqr
    group3 = kjl
        capture0 = kjl
    group4 = mno
        capture0 = mno
    group5 = pqr
        capture0 = pqr

আসুন মাত্র প্রথম ম্যাচটি বিশ্লেষণ করুন (match0 )।

যেহেতু আপনি দেখতে পারেন সেখানে তিনটি নাবালক গ্রুপ : group3, group4এবংgroup5

    group3 = kjl
        capture0 = kjl
    group4 = mno
        capture0 = mno
    group5 = pqr
        capture0 = pqr

সেই গোষ্ঠী (3-5) 'কারণে তৈরি করা হয়েছিল subpattern ' (...)(...)(...)এর প্রধান প্যাটার্ন (dog(cat(...)(...)(...)))

group3এর ক্যাপচার ( capture0) এর সাথে মিলের মান । (ক্ষেত্রে যেমন group4এবং group5)। এটা এ কারণে যে এর কোন গ্রুপ পুনরাবৃত্তি হয় মত (...){3}


ঠিক আছে, আসুন আরেকটি উদাহরণ বিবেচনা করুন যেখানে একটি গ্রুপ পুনরাবৃত্তি রয়েছে

আমরা মিলেছে করা থেকে (উপরে দেখানো কোডটি জন্য) রেগুলার এক্সপ্রেশন প্যাটার্ন পরিবর্তন যদি (dog(cat(...)(...)(...)))করতে (dog(cat(...){3})), আপনি বিজ্ঞপ্তি পাবেন নিচের যে গ্রুপ পুনরাবৃত্তি :(...){3}

এখন আউটপুট পরিবর্তন হয়েছে:

match0 = dogcatabcdefghi
    group0 = dogcatabcdefghi
        capture0 = dogcatabcdefghi
    group1 = dogcatabcdefghi
        capture0 = dogcatabcdefghi
    group2 = catabcdefghi
        capture0 = catabcdefghi
    group3 = ghi
        capture0 = abc
        capture1 = def
        capture2 = ghi

match1 = dogcatkjlmnopqr
    group0 = dogcatkjlmnopqr
        capture0 = dogcatkjlmnopqr
    group1 = dogcatkjlmnopqr
        capture0 = dogcatkjlmnopqr
    group2 = catkjlmnopqr
        capture0 = catkjlmnopqr
    group3 = pqr
        capture0 = kjl
        capture1 = mno
        capture2 = pqr

আবার, আসুন মাত্র প্রথম ম্যাচটি বিশ্লেষণ করুন (match0 )।

আর কোনও ছোটখাটো গোষ্ঠী নেই group4 এবং পুনরাবৃত্তিরgroup5 কারণে ( > n} যার মধ্যে n> = 2 ) সেগুলিকে একটি একক দলে একীভূত করা হয়েছে(...){3} group3

এই ক্ষেত্রে, group3মান এটির সাথে মিলিত হয় capture2( শেষ ক্যাপচার) অন্য কথায় )।

সুতরাং যদি আপনি সেই সমস্ত 3 ভেতরের যেমনটি হবে ( capture0, capture1, capture2) আপনি গ্রুপের মাধ্যমে চক্র করতে হবেCaptures সংগ্রহ।

উপসংহারটি হ'ল: আপনি কীভাবে আপনার প্যাটার্নের গ্রুপগুলি ডিজাইন করেন সেদিকে মনোযোগ দিন। আপনি আপফ্রন্ট চিন্তা করা উচিত কি আচরণ গ্রুপের স্পেসিফিকেশন, মত ঘটায় (...)(...), (...){2}বা (.{3}){2}ইত্যাদি


আশা করি এটি ক্যাপচার , গ্রুপ এবং ম্যাচগুলির মধ্যে পার্থক্য সম্পর্কে কিছুটা আলোকপাত করতে সহায়তা করবে ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.