NET Regex- এ নামী ক্যাপচারিং গ্রুপগুলিতে আমি কীভাবে অ্যাক্সেস করব?


255

সি # তে নামযুক্ত ক্যাপচারিং গ্রুপগুলি কীভাবে ব্যবহার করতে হয় তা ব্যাখ্যা করার জন্য একটি ভাল উত্স খুঁজে পেতে আমার বেশ কষ্ট হচ্ছে। আমার এখন পর্যন্ত এই কোডটি রয়েছে:

string page = Encoding.ASCII.GetString(bytePage);
Regex qariRegex = new Regex("<td><a href=\"(?<link>.*?)\">(?<name>.*?)</a></td>");
MatchCollection mc = qariRegex.Matches(page);
CaptureCollection cc = mc[0].Captures;
MessageBox.Show(cc[0].ToString());

তবে এটি সর্বদা সম্পূর্ণ লাইনটি দেখায়:

<td><a href="/path/to/file">Name of File</a></td> 

আমি বিভিন্ন ওয়েবসাইটে খুঁজে পেয়েছি এমন আরও কয়েকটি "পদ্ধতি" নিয়ে পরীক্ষা-নিরীক্ষা করেছি তবে আমি একই ফল পেতে থাকি।

কীভাবে আমি আমার রেজেজেলে উল্লিখিত নামধারী ক্যাপচারিং গ্রুপগুলিতে অ্যাক্সেস করতে পারি?


3
পিছনে রেফারেন্সটি (? <লিঙ্ক>। *) ফর্ম্যাটে থাকতে হবে এবং (? <লিঙ্ক>। *?) নয়
তাই ব্যবহারকারী

11
এফওয়াইআই: আপনি যদি কোনও এক্সএমএল ফাইলের মধ্যে একটি নামকৃত ক্যাপচার গ্রুপটি সংরক্ষণ করার চেষ্টা করছেন তবে এটি <>এটি ভেঙে দেবে। আপনি (?'link'.*)এই ক্ষেত্রে পরিবর্তে ব্যবহার করতে পারেন । সম্পূর্ণরূপে এই প্রশ্নের প্রাসঙ্গিক নয় কিন্তু আমি এখানে ".net নামে ক্যাপচার গ্রুপ" তাই আমি নিশ্চিত অন্যান্য ব্যক্তিদের হিসাবে ভাল হয় আছি ... একটি গুগল সার্চ থেকে অবতরণ করেছে
rtpHarry

1
চমৎকার উদাহরণ Stackoverflow লিঙ্ক: stackoverflow.com/a/1381163/463206 এছাড়াও, @rtpHarry, কোন <>তা ভঙ্গ করা হবে না। আমি myRegex.GetGroupNames()XML উপাদান নাম হিসাবে সংগ্রহটি ব্যবহার করতে সক্ষম হয়েছি ।
রাডারবাব

উত্তর:


263

ম্যাচ অবজেক্টের গ্রুপ সংগ্রহ ব্যবহার করুন, এটি ক্যাপচারিং গ্রুপের নামের সাথে সূচী করে, যেমন eg

foreach (Match m in mc){
    MessageBox.Show(m.Groups["link"].Value);
}

10
ব্যবহার করবেন না var m, যেহেতু এটি একটি হবে object
থমাস ওয়েলার

111

আপনি Groupsফলস্বরূপ Matchঅবজেক্টের সম্পত্তির সূচকের কাছে এটি প্রেরণ করে নামকরণ ক্যাপচার গ্রুপ স্ট্রিং নির্দিষ্ট করেন ।

এখানে একটি ছোট উদাহরণ:

using System;
using System.Text.RegularExpressions;

class Program
{
    static void Main()
    {
        String sample = "hello-world-";
        Regex regex = new Regex("-(?<test>[^-]*)-");

        Match match = regex.Match(sample);

        if (match.Success)
        {
            Console.WriteLine(match.Groups["test"].Value);
        }
    }
}

10

নিম্নলিখিত কোডের নমুনাটি, মাঝে মাঝে স্থান অক্ষরের ক্ষেত্রেও প্যাটার্নটির সাথে মিলবে। অর্থাত:

<td><a href='/path/to/file'>Name of File</a></td>

পাশাপাশি:

<td> <a      href='/path/to/file' >Name of File</a>  </td>

ইনপুট htmlTd স্ট্রিংটি প্যাটার্নটির সাথে মেলে কিনা তার উপর নির্ভর করে পদ্ধতিটি সত্য বা মিথ্যা প্রত্যাবর্তন করে। যদি এটি মেলে, আউট প্যারামগুলিতে যথাক্রমে লিঙ্ক এবং নাম থাকে।

/// <summary>
/// Assigns proper values to link and name, if the htmlId matches the pattern
/// </summary>
/// <returns>true if success, false otherwise</returns>
public static bool TryGetHrefDetails(string htmlTd, out string link, out string name)
{
    link = null;
    name = null;

    string pattern = "<td>\\s*<a\\s*href\\s*=\\s*(?:\"(?<link>[^\"]*)\"|(?<link>\\S+))\\s*>(?<name>.*)\\s*</a>\\s*</td>";

    if (Regex.IsMatch(htmlTd, pattern))
    {
        Regex r = new Regex(pattern,  RegexOptions.IgnoreCase | RegexOptions.Compiled);
        link = r.Match(htmlTd).Result("${link}");
        name = r.Match(htmlTd).Result("${name}");
        return true;
    }
    else
        return false;
}

আমি এটি পরীক্ষা করেছি এবং এটি সঠিকভাবে কাজ করে।


1
আমাকে স্মরণ করিয়ে দেওয়ার জন্য ধন্যবাদ যে কোঁকড়া ধনুর্বন্ধনী গ্রুপগুলি অ্যাক্সেস করতে পারে। ${1}জিনিসগুলিকে আরও সরল রাখতে আমি আঁকড়ে থাকতে পছন্দ করি ।
ম্যাগনাস স্মিথ

এটি পুরোপুরি প্রশ্নের উত্তর দেয়, তবে কিছু সমস্যা রয়েছে যা এখানে ব্যাখ্যা করার জন্য অনেক দীর্ঘ, তবে আমি নীচে আমার
উত্তরটিতে

1

অতিরিক্ত হিসাবে যদি কারও ব্যবহারের ক্ষেত্রে থাকে যেখানে রেগেক্স অবজেক্টে অনুসন্ধান চালানোর আগে তার গ্রুপ নাম প্রয়োজন সে ব্যবহার করতে পারে:

var regex = new Regex(pattern); // initialized somewhere
// ...
var groupNames = regex.GetGroupNames();

1

এই উত্তরগুলি রশ্মী পণ্ডিতের উত্তরে উন্নতি করে , যা বিশ্রামের চেয়ে এক দিক থেকে ভাল কারণ এটি মনে হয় যে প্রশ্নটিতে বর্ণিত সঠিক সমস্যাটি সম্পূর্ণ সমাধান করেছে।

খারাপ অংশটি হ'ল অদক্ষ এবং নিয়মিত IgnoreCase বিকল্পটি ব্যবহার করে না।

অপর্যাপ্ত অংশটি হ'ল রেজেেক্সটি নির্মাণ এবং সম্পাদন করা ব্যয়বহুল হতে পারে এবং এর উত্তরে এটি কেবল একবার তৈরি করা যেতে পারে ( Regex.IsMatchকলিংটি কেবল দৃশ্যের পিছনে আবার রেজেক্স তৈরি করছিল)। আর Matchপদ্ধতি পারে শুধুমাত্র একবার বলা হয়েছে এবং একটি পরিবর্তনশীল সঞ্চিত এবং তারপর linkএবং nameকল করা উচিত Resultযে পরিবর্তনশীল থেকে।

এবং IgnoreCase বিকল্পটি কেবল Matchঅংশে ব্যবহৃত হয়েছিল তবে অংশে নয় Regex.IsMatch

আমি কেবল একবার এটির নির্মাণের জন্য পদ্ধতির বাইরেও রেজেক্স সংজ্ঞাটি স্থানান্তরিত করেছি (আমি মনে করি বোধগম্য পদ্ধতি যদি আমরা সেই RegexOptions.Compiledবিকল্পটি সহ সমাবেশটি সঞ্চয় করি তবে )।

private static Regex hrefRegex = new Regex("<td>\\s*<a\\s*href\\s*=\\s*(?:\"(?<link>[^\"]*)\"|(?<link>\\S+))\\s*>(?<name>.*)\\s*</a>\\s*</td>",  RegexOptions.IgnoreCase | RegexOptions.Compiled);

public static bool TryGetHrefDetails(string htmlTd, out string link, out string name)
{
    var matches = hrefRegex.Match(htmlTd);
    if (matches.Success)
    {
        link = matches.Result("${link}");
        name = matches.Result("${name}");
        return true;
    }
    else
    {
        link = null;
        name = null;
        return false;
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.