জাভাতে নিয়মিত প্রকাশের জন্য কীভাবে টেক্সট এড়াতে হবে


320

এটিকে নিয়মিত অভিব্যক্তিতে অন্তর্ভুক্ত করার জন্য জাভাতে স্বেচ্ছাসেবী পাঠ্য থেকে বাঁচার জন্য অন্তর্নির্মিত উপায় আছে? উদাহরণস্বরূপ, যদি আমার ব্যবহারকারীরা "$ 5" প্রবেশ করে তবে আমি ইনপুট শেষ হওয়ার পরে "5" এর চেয়ে ঠিক এটির সাথে মিল রাখতে চাই।

উত্তর:


450

যেহেতু জাভা 1.5, হ্যাঁ :

Pattern.quote("$5");

88
দয়া করে মনে রাখবেন না যে এটি নিজেই স্ট্রিংটি এড়ায় না, \Qএবং এটি ব্যবহার করে এবং এটি মোড়ানো \E। এটি অপ্রত্যাশিত ফলাফলের দিকে পরিচালিত করতে পারে, উদাহরণস্বরূপ Pattern.quote("*.wav").replaceAll("*",".*")ফলাফল হিসাবে \Q.*.wav\Eএবং না .*\.wavযেমন আপনি আশা করতে পারেন।
ম্যাথিয়াস রাঙ্গো

11
@ পারমেলিয়ন আপনি কেন এই ফু (এক্স)? বার () == এক্স.বার () আশা করবেন?
মাইকেল

7
@ পারমেলিয়ন আমি মনে করি আপনি ব্যবহারের ক্ষেত্রে ভুল বোঝাবুঝি করছেন।
ভাইকিংস্টিভ

18
আমি কেবল এটি উল্লেখ করতে চাই না যে পালানোর এই উপায়টি আপনি পরে প্রকাশিত অভিব্যক্তিগুলিতেও পালানো প্রযোজ্য । এটি অবাক হতে পারে। যদি আপনি না "mouse".toUpperCase().replaceAll("OUS","ic")এটা ফিরে আসবে MicE। আপনি এটা ফিরে যাওয়ার আশা would't MICEকারণ আপনার প্রয়োগ করেননি toUpperCase()উপর ic। আমার উদাহরণে পাশাপাশি সন্নিবেশনে quote()প্রয়োগ করা হয় । আপনাকে অন্য কিছু করতে হবে, সম্ভবত কাজ করবে, তবে এটি বিপরীত। .*replaceAll().replaceAll("*","\\E.*\\Q")
ম্যাথিয়াস রাঞ্জে

2
@ পারম্যালন যদি এটি পৃথক পলায়ন যোগ করে কাজ করে, তবে আপনার প্রাথমিক উদাহরণটি এখনও আপনি যা চান তা করতে পারত না ... যদি এটি স্বতন্ত্রভাবে চরিত্রগুলি থেকে পালিয়ে যায় তবে এটি *.wavরেজেক্স প্যাটার্নে \*\.wavপরিণত হবে, এবং প্রতিস্থাপনকৃত সমস্ত এটি রূপান্তরিত করবে \.*\.wav, যার অর্থ এটি হবে ফাইলগুলির মিল মেলে যার নাম অনুসারে একটি নির্বিচার সংখ্যক পিরিয়ড থাকে .wav। আপনার সম্ভবত প্রয়োজন ছিল replaceAll("\\*", ".*")যদি তারা আরও ভঙ্গুর বাস্তবায়নের সাথে চলে যেত যেগুলি সমস্ত সম্ভাব্য সক্রিয় রেজেক্স চর্যাচটারগুলি স্বীকৃতি দেওয়ার জন্য এবং স্বতন্ত্রভাবে সেগুলি থেকে পালিয়ে যাওয়ার উপর নির্ভর করে ... তাই এত সহজ?
থিওডোর মুরডক

112

মধ্যে পার্থক্য Pattern.quoteএবং Matcher.quoteReplacementআমি নিম্নলিখিত উদাহরণে দেখেছি আমাকে স্পষ্ট ছিল না

s.replaceFirst(Pattern.quote("text to replace"), 
               Matcher.quoteReplacement("replacement text"));

29
বিশেষতঃ, Pattern.quoteরেগেক্স অনুসন্ধানের স্ট্রিংগুলিতে, যেমন। | + () Matcher.quoteReplacementইত্যাদিগুলিতে বিশেষ অক্ষর প্রতিস্থাপন করে এবং প্রতিস্থাপনের জন্য \ 1 এর মতো প্রতিস্থাপনের স্ট্রিংগুলিতে বিশেষ অক্ষরগুলি প্রতিস্থাপন করে।
স্টিভেন

9
আমি রাজি নই। প্যাটার্ন.কোইটি তার যুক্তিটিকে \ Q এবং \ E দিয়ে মোড় দেয়। এটি বিশেষ চরিত্রগুলি এড়ায় না।
ডেভিড মেডিনেটস

5
ম্যাচার.কোটরেপ্লেসমেন্ট ("4 $ &% $") "4 \ $ &% \ $" উত্পাদন করে। এটি বিশেষ চরিত্রগুলি থেকে পালিয়ে যায়।
ডেভিড মেডিনেটস

4
অন্য কথায়: quoteReplacementকেবল দুটি প্রতীক সম্পর্কে যত্নশীল $এবং \ যা উদাহরণস্বরূপ প্রতিস্থাপনের স্ট্রিংগুলিকে ব্যাকরেফারেন্স হিসাবে ব্যবহার করতে পারে $1বা \1। সুতরাং এটি কোনও রেজেক্সকে পালাতে / উদ্ধৃত করতে অবশ্যই ব্যবহার করা উচিত নয়।
সেবাস্তিয়ানএইচ

1
অসাধারণ. এখানে একটি উদাহরণ যেখানে আমরা প্রতিস্থাপন করতে চান হয় $Group$সঙ্গে T$UYO$HI$প্রতীক উভয় প্যাটার্ন এবং প্রতিস্থাপন বিশেষ হল:"$Group$ Members".replaceFirst(Pattern.quote("$Group$"), Matcher.quoteReplacement("T$UYO$HI"))
অরুণ

29

প্রতিক্রিয়া জানাতে দেরি হতে পারে তবে আপনি এটি ব্যবহার করতে পারেন Pattern.LITERALযা বিন্যাস করার সময় সমস্ত বিশেষ অক্ষরকে উপেক্ষা করবে:

Pattern.compile(textToFormat, Pattern.LITERAL);

এটি বিশেষত দুর্দান্ত কারণ আপনি এটিকে একত্রিত করতে পারেনPattern.CASE_INSENSITIVE
এমজানিউক

13

আমি মনে করি আপনি কি পরে আছেন \Q$5\E। আরও দেখুন Pattern.quote(s)Java5 চালু।

বিশদ জন্য প্যাটার্ন javadoc দেখুন ।


লিটারাল পতাকাটি ব্যবহার করার ও এর মধ্যে কোনও পার্থক্য থাকলে আমি কৌতূহলী, যেহেতু জাভাডোক বলে যে লিটারাল চালু এবং বন্ধ করতে কোনও এম্বেডড পতাকা নেই: java.sun.com/j2se/1.5.0/docs/api/java/ ইউজার / রেজেক্স /…
ক্রিস মাজোলা

15
মনে রাখবেন যে আক্ষরিক অর্থে \ Q এবং \ E ব্যবহার করা ঠিক আছে যদি আপনি নিজের ইনপুটটি জানেন। প্যাটার্ন.কোয়েট (গুলি) সেই ক্ষেত্রেও পরিচালনা করবে যেখানে আপনার পাঠ্যে আসলে এই অনুক্রমগুলি রয়েছে contains
জেরেমি হুইস্ক্যাম্প

10

প্রথম বন্ধ, যদি

  • আপনি সমস্ত প্রতিস্থাপন ব্যবহার করুন ()
  • আপনি ম্যাচার.কোটের রিপ্লেসমেন্ট () ব্যবহার করবেন না
  • প্রতিস্থাপন করা পাঠ্যটিতে একটি $ 1 অন্তর্ভুক্ত রয়েছে

এটি শেষে একটি 1 লাগবে না। এটি প্রথম মিলিত গোষ্ঠীর জন্য অনুসন্ধানের রেজেক্সের দিকে নজর দেবে এবং এটিতে এটি সাব-ইন করবে the প্রতিস্থাপন পাঠ্যে text 1, $ 2 বা $ 3 এর অর্থ: অনুসন্ধানের নিদর্শন থেকে মিলছে গোষ্ঠী।

আমি প্রায়শই .properties ফাইলগুলিতে পাঠ্যের দীর্ঘ স্ট্রিংগুলি প্লাগ করি, তারপরে সেগুলি থেকে ইমেল বিষয়বস্তু এবং সংস্থা তৈরি করি। প্রকৃতপক্ষে, এটি স্প্রিং ফ্রেমওয়ার্কে আই 18 এন করার ডিফল্ট উপায় বলে মনে হয়। আমি স্টারগুলিতে এক্সএমএল ট্যাগগুলি, স্থানধারক হিসাবে রেখেছি এবং আমি রানটাইম সময়ে এক্সএমএল ট্যাগগুলি প্রতিস্থাপন করতে প্রতিস্থাপন (সমস্ত) ব্যবহার করি।

আমি একটি ইস্যুতে দৌড়েছি যেখানে কোনও ব্যবহারকারী ডলারের চিহ্ন সহ ডলার-সেন্ট সেন্ট ফিগার করে। প্রতিস্থাপনআল () নীচে একটি স্ট্র্যাকট্রেসে দেখানো সহ এটিতে চেপে গেছে:

java.lang.IndexOutOfBoundsException: No group 3
at java.util.regex.Matcher.start(Matcher.java:374)
at java.util.regex.Matcher.appendReplacement(Matcher.java:748)
at java.util.regex.Matcher.replaceAll(Matcher.java:823)
at java.lang.String.replaceAll(String.java:2201)

এই ক্ষেত্রে, ব্যবহারকারী তাদের ইনপুটটিতে কোথাও "$ 3" প্রবেশ করেছিল এবং সমস্ত () তৃতীয় মিলে যাওয়া গ্রুপের জন্য অনুসন্ধানের রেজেক্সে সন্ধান করতে গিয়েছিল, একটিও খুঁজে পায়নি এবং ছুঁড়ে ফেলেছে।

প্রদত্ত:

// "msg" is a string from a .properties file, containing "<userInput />" among other tags
// "userInput" is a String containing the user's input

প্রতিস্থাপন

msg = msg.replaceAll("<userInput \\/>", userInput);

সঙ্গে

msg = msg.replaceAll("<userInput \\/>", Matcher.quoteReplacement(userInput));

সমস্যার সমাধান। ব্যবহারকারী ইস্যু ছাড়াই ডলারের লক্ষণ সহ যে কোনও ধরণের অক্ষর রেখে দিতে পারে। এটি আপনার প্রত্যাশা মতো ঠিক আচরণ করেছিল।


6

সুরক্ষিত প্যাটার্ন রাখতে আপনি সমস্ত চিহ্নকে "all" দিয়ে প্রতিস্থাপন করতে পারেন, সংখ্যা এবং অক্ষর বাদে। এবং তারপরে আপনি এই সুরক্ষিত প্যাটার্নটিতে আপনার বিশেষ চিহ্নগুলি রাখতে পারেন যাতে এই প্যাটার্নটি বোকা উদ্ধৃত পাঠ্যের মতো নয়, তবে সত্যিই কোনও প্যাটের মতো, তবে নিজের নিজস্ব own ব্যবহারকারীর বিশেষ চিহ্ন ছাড়া।

public class Test {
    public static void main(String[] args) {
        String str = "y z (111)";
        String p1 = "x x (111)";
        String p2 = ".* .* \\(111\\)";

        p1 = escapeRE(p1);

        p1 = p1.replace("x", ".*");

        System.out.println( p1 + "-->" + str.matches(p1) ); 
            //.*\ .*\ \(111\)-->true
        System.out.println( p2 + "-->" + str.matches(p2) ); 
            //.* .* \(111\)-->true
    }

    public static String escapeRE(String str) {
        //Pattern escaper = Pattern.compile("([^a-zA-z0-9])");
        //return escaper.matcher(str).replaceAll("\\\\$1");
        return str.replaceAll("([^a-zA-Z0-9])", "\\\\$1");
    }
}

আপনাকে স্পেস থেকে বাঁচতে হবে না। সুতরাং আপনি "([[^ a-zA-z0-9])" তে আপনার প্যাটার্নটি আটকে রাখতে পারেন।
এরেল সেগাল-হালেভি

5
ছোট টাইপ, বড় পরিণতি: "([^ a-zA-z0-9])" এছাড়াও মেলে না (অর্থাত্ পালাতে পারে না) [, \,], ^ যা আপনি অবশ্যই পালাতে চান! টাইপোটি দ্বিতীয় 'জেড' যা 'জেড' হওয়া উচিত, অন্যথায় এএসসিআইআই 65 থেকে এএসসিআইআই 122 পর্যন্ত সমস্ত কিছু অন্তর্ভুক্ত রয়েছে
জেফিরো

3

প্যাটার্ন.কোইট ("ব্লেবলা") দুর্দান্ত কাজ করে।

প্যাটার্ন.কোয়েট () সুন্দরভাবে কাজ করে। এটি " \ Q " এবং " \ E " অক্ষরগুলির সাথে বাক্যটি সংযুক্ত করে এবং যদি এটি "\ Q" এবং "\ E" এড়িয়ে যায়। যাইহোক, আপনার যদি সত্যিকারের নিয়মিত এক্সপ্রেশন এস্কেপিংয়ের প্রয়োজন হয় (বা কাস্টম পলায়ন), আপনি এই কোডটি ব্যবহার করতে পারেন:

String someText = "Some/s/wText*/,**";
System.out.println(someText.replaceAll("[-\\[\\]{}()*+?.,\\\\\\\\^$|#\\\\s]", "\\\\$0"));

এই পদ্ধতিটি ফিরে আসে: কিছু / \ গুলি / ডব্লিউটেক্সট * / \, **

উদাহরণ এবং পরীক্ষার জন্য কোড:

String someText = "Some\\E/s/wText*/,**";
System.out.println("Pattern.quote: "+ Pattern.quote(someText));
System.out.println("Full escape: "+someText.replaceAll("[-\\[\\]{}()*+?.,\\\\\\\\^$|#\\\\s]", "\\\\$0"));

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