নিয়মিত এক্সপ্রেশন ব্যবহার করে মাল্টলাইন পাঠ্য মিলান


174

আমি জাভা ব্যবহার করে একাধিক লাইনের পাঠ্য মেলাতে চেষ্টা করছি। আমি যখন মডিফায়ারের সাহায্যে Patternক্লাসটি ব্যবহার করি, তখন আমি Pattern.MULTILINEমেলতে সক্ষম হয়েছি, তবে আমি এটি করতে সক্ষম হই না(?m).

একই পদ্ধতি (?m)ব্যবহার String.matchesকরে এবং ব্যবহার করে বলে মনে হচ্ছে না।

আমি নিশ্চিত যে আমি কিছু অনুপস্থিত, তবে কী হবে জানি না। নিয়মিত প্রকাশে খুব একটা ভাল না Am

এই আমি চেষ্টা করেছিলাম

String test = "User Comments: This is \t a\ta \n test \n\n message \n";

String pattern1 = "User Comments: (\\W)*(\\S)*";
Pattern p = Pattern.compile(pattern1, Pattern.MULTILINE);
System.out.println(p.matcher(test).find());  //true

String pattern2 = "(?m)User Comments: (\\W)*(\\S)*";
System.out.println(test.matches(pattern2));  //false - why?

উত্তর:


298

প্রথমত, আপনি একটি ভুল অনুমানের অধীনে সংশোধক ব্যবহার করছেন।

Pattern.MULTILINEবা (?m)জাভাটিকে অ্যাঙ্করগুলি গ্রহণ করতে ^এবং $প্রতিটি লাইনের শুরুতে এবং শেষে ম্যাচ করতে বলে (অন্যথায় তারা কেবল পুরো স্ট্রিংয়ের শুরুতে / শেষে মিলবে)।

Pattern.DOTALLবা (?s)জাভা কে বিন্দুটিকেও নতুন লাইনের অক্ষরগুলির সাথে মেলে দেওয়ার অনুমতি দেয়।

দ্বিতীয়ত, আপনার ক্ষেত্রে, রেজেক্স ব্যর্থ হয়েছে কারণ আপনি সেই matches()পদ্ধতিটি ব্যবহার করছেন যা প্রত্যাশা করে যে রেজেক্স পুরো স্ট্রিংয়ের সাথে মিলবে - যা অবশ্যই কাজ করে না কারণ কিছু অক্ষর (\\W)*(\\S)*মিলে যাওয়ার পরে অবশিষ্ট রয়েছে ।

সুতরাং আপনি যদি কেবল স্ট্রিংটি সন্ধান করেন যা শুরু হয় User Comments:, রেজেক্স ব্যবহার করুন

^\s*User Comments:\s*(.*)

সঙ্গে Pattern.DOTALLবিকল্প:

Pattern regex = Pattern.compile("^\\s*User Comments:\\s+(.*)", Pattern.DOTALL);
Matcher regexMatcher = regex.matcher(subjectString);
if (regexMatcher.find()) {
    ResultString = regexMatcher.group(1);
} 

ResultString তারপরে পাঠ্য থাকবে User Comments:


আমি এমন একটি প্যাটার্ন সন্ধান করার চেষ্টা করছি যা "ব্যবহারকারীর মন্তব্য:" দিয়ে শুরু হওয়া কোনও স্ট্রিংয়ের সাথে মেলে। এর পরে "ব্যবহারকারীর মন্তব্যসমূহ:" হ'ল এমন কিছু যা ব্যবহারকারী কোনও টেক্সেরিয়ায় প্রবেশ করে এবং তাই এতে নতুন কিছু এমনকি লাইনও থাকতে পারে । দেখে মনে হচ্ছে রেগেজেসে আমার অনেক কিছু শেখা দরকার ...
নিবাস

2
এটি কাজ করে (ধন্যবাদ!) আমি প্যাটার্নটি চেষ্টা করেছি (?s)User Comments:\s*(.*)। @ অমরঘোষের উত্তর থেকে আমি প্যাটার্নটি পেয়েছি User Comments: [\\s\\S]*। এর মধ্যে আরও ভাল বা প্রস্তাবিত উপায় রয়েছে বা এটি করার দুটি মাত্র ভিন্ন উপায়?
নিভাস

3
তারা উভয় একই অর্থ; [\s\S]কিছুটা স্পষ্টত ("সাদা বর্ণমালা বা শ্বেতক্ষেত্রের যে কোনও চরিত্রের সাথে মেলে") .পড়া সহজ, তবে নতুন লাইনের অন্তর্ভুক্ত রয়েছে কি না তা খুঁজে পাওয়ার জন্য আপনাকে (?s)বা DOTALLপরিবর্তকের সন্ধান করতে হবে। ্যদসব .সঙ্গে Pattern.DOTALLপতাকা সেট (এই পড়া এবং তুলনায় মনে রাখা সহজ হয় (?s)আমার মতে আপনি ব্যবহার করা উচিত কি আপনার সাথে সবচেয়ে আরামদায়ক
টিম Pietzcker

.*সঙ্গে DOTALLআরও পাঠযোগ্য। আমি অন্যটি ব্যবহার করে দেখিয়েছি যে সমস্যাটি স্ট্রিমার ম্যাচ এবং ম্যাচারের মধ্যে পার্থক্য in +1
আমারঘোষ

আমি পছন্দ .*সঙ্গে Pattern.DOTALL, কিন্তু সঙ্গে যেতে হবে (? গুলি) কারণ আমি ব্যবহার করতে হবে String.matches
Nivas

42

মাল্টলাইন পতাকার সাথে এর কোনও যোগসূত্র নেই; আপনি যা দেখছেন তা হ'ল পদ্ধতি find()এবং matches()পদ্ধতির মধ্যে পার্থক্য । টার্গেট স্ট্রিংয়ের কোথাও কোনওfind() ম্যাচ পাওয়া গেলে সফল হয় , যখন রেজেক্সটি পুরো স্ট্রিংয়ের সাথে মিলের প্রত্যাশা করে ।matches()

Pattern p = Pattern.compile("xyz");

Matcher m = p.matcher("123xyzabc");
System.out.println(m.find());    // true
System.out.println(m.matches()); // false

Matcher m = p.matcher("xyz");
System.out.println(m.matches()); // true

তদুপরি, MULTILINEআপনি যা ভাবেন তা বোঝায় না। অনেকের এই সিদ্ধান্তে ঝাঁপিয়ে পড়ে মনে হয় যে আপনার টার্গেট স্ট্রিংয়ে নতুন লাইন থাকলে - এটিতে যদি একাধিক যৌক্তিক লাইন থাকে তবে আপনাকে সেই পতাকাটি ব্যবহার করতে হবে। আমি এখানে এসও তে বেশ কয়েকটি উত্তর দেখেছি তবে বাস্তবে, সমস্ত পতাকাটি অ্যাঙ্করগুলির আচরণ পরিবর্তন করে ^এবং $

সাধারণত ^লক্ষ্য স্ট্রিংয়ের একেবারে শুরুর সাথে $মেলে এবং একেবারে শেষের সাথে মেলে (বা শেষের দিকে একটি নিউলাইনের আগে, তবে আমরা এটি এখনই বাদ দিয়ে দেব)। তবে স্ট্রিংয়ে যদি নতুন লাইন থাকে তবে আপনি মাল্টলাইন পতাকাটি সেট করে পুরো স্ট্রিংয়ের শুরু এবং শেষ নয়, কোনও লজিকাল লাইনের শুরু এবং শেষের জন্য বাছাই করতে ^এবং বেছে নিতে পারেন $

তাই কি ভুলে MULTILINE মানে এবং মাত্র স্মরণ এটা কি করে : এর আচরণগুলিকে পরিবর্তন করে ^এবং $নোঙ্গর। DOTALLমোডটি প্রথমে "একক-লাইন" নামে পরিচিত ছিল (এবং এখনও পার্ল এবং .NET সহ কিছু স্বাদে রয়েছে) এবং এটি সর্বদা একই ধরণের বিভ্রান্তির সৃষ্টি করে। আমরা ভাগ্যবান যে জাভা দেবগণ সেই ক্ষেত্রে আরও বর্ণনামূলক নামের সাথে চলেছিলেন, তবে "মাল্টলাইন" মোডের কোনও যুক্তিসঙ্গত বিকল্প ছিল না।

পার্লে, যেখানে এই সমস্ত উন্মাদনা শুরু হয়েছিল, তারা তাদের ভুল স্বীকার করেছে এবং পার্ল 6 রেজিজেসে "মাল্টলাইন" এবং "একক লাইন" উভয় পদ্ধতি থেকে মুক্তি পেয়েছে। আরও বিশ বছরে, সম্ভবত বিশ্বের বাকী অংশগুলি অনুসরণ করবে।


5
বিশ্বাস করা কঠিন যে তারা "# ম্যাচস" পদ্ধতিটির নামটি "সমস্ত মিলছে" ইয়াকে বোঝাতে বোঝায়
রোজারডপ্যাক

@ অ্যালান-মুর দুঃখিত, এটি সঠিক হলেও [আরও ঘুম দরকার :)]
রেমন্ড নাসিফ

22

str.matches(regex) Pattern.matches(regex, str)প্যাটার্ন এবং রিটার্নের বিপরীতে পুরো ইনপুট ক্রমটি মেলানোর চেষ্টা করে এমন আচরণ করে

trueযদি এবং কেবলমাত্র, সম্পূর্ণ ইনপুট ক্রম এই ম্যাচারের প্যাটার্নের সাথে মেলে

যেখানে প্যাটার্ন এবং রিটার্নের সাথে মেলে এমন ইনপুট ক্রমের পরবর্তী অনুচ্ছেদটি সন্ধান matcher.find() করার চেষ্টা করা হয়েছে

trueযদি, এবং কেবল যদি, একটি subsequence ইনপুট ক্রম এই মিলকারীর এর ধরণের সাথে মেলা

সুতরাং সমস্যাটি রেইজেক্সের সাথে। নিম্নলিখিত চেষ্টা করুন।

String test = "User Comments: This is \t a\ta \ntest\n\n message \n";

String pattern1 = "User Comments: [\\s\\S]*^test$[\\s\\S]*";
Pattern p = Pattern.compile(pattern1, Pattern.MULTILINE);
System.out.println(p.matcher(test).find());  //true

String pattern2 = "(?m)User Comments: [\\s\\S]*^test$[\\s\\S]*";
System.out.println(test.matches(pattern2));  //true

এইভাবে সংক্ষেপে, (\\W)*(\\S)*আপনার প্রথম রেজেক্সের অংশটি *শূন্য বা তার বেশি উপস্থিতি হিসাবে একটি খালি স্ট্রিংয়ের সাথে মেলে এবং আসল ম্যাচিং স্ট্রিংটি User Comments:আপনার প্রত্যাশা মতো পুরো স্ট্রিং নয়। দ্বিতীয়টি ব্যর্থ হয় যেহেতু এটি পুরো স্ট্রিংয়ের সাথে মেলে যাবার চেষ্টা করে তবে এটি \\Wকোনও শব্দের অক্ষরের সাথে মেলে না যেমন , [^a-zA-Z0-9_]এবং প্রথম অক্ষরটি Tএকটি শব্দের অক্ষর।


আমি "ব্যবহারকারীর মন্তব্য" দিয়ে শুরু হওয়া কোনও স্ট্রিংয়ের সাথে মিল রাখতে চাই এবং স্ট্রিংয়ে নতুন লাইনও থাকতে পারে। সুতরাং আমি প্যাটার্নটি ব্যবহার করেছি User Comments: [\\s\\S]*এবং এটি কাজ করেছে। (ধন্যবাদ!) @ টিমের উত্তর থেকে আমি প্যাটার্নটি পেয়েছি User Comments:(.*), এটিও ঠিক আছে এখন, এইগুলির মধ্যে একটি প্রস্তাবিত বা আরও ভাল উপায় আছে, বা এটি কেবল একইভাবে করার দুটি উপায়?
নিবাস

@ নিবাস আমার ধারণা নেই যে পারফরম্যান্স অনুযায়ী কোনও পার্থক্য থাকবে; তবে আমি মনে করি পতাকার (.*)পাশাপাশি DOTALLপতাকাটি আরও স্পষ্ট / পঠনযোগ্য([\\s\\S]*)
আমারঘোষ osh

এটি সেরা উত্তর .... মাল্টিলাইন সক্ষমতার জন্য জাভা কোড এবং প্যাটার্ন স্ট্রিং বিকল্পগুলিতে উভয়ই অ্যাক্সেস সরবরাহ করে।
গোল্ডবিশপ

0

মাল্টিলাইন পতাকাটি রেগেক্সকে প্রতিটি লাইনের সাথে প্যাটার্নটি মেলে ধরতে বলেছে আপনার উদ্দেশ্যে একটি ওয়াইল্ড কার্ডই যথেষ্ট।

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