জাভাতে সংবেদনশীল আক্ষরিক সাবস্ট্রিংগুলি কীভাবে প্রতিস্থাপন করবেন


130

স্ট্রিংয়ের পদ্ধতিটি ব্যবহার করে replace(CharSequence target, CharSequence replacement), আমি কীভাবে লক্ষ্য কেস-সংবেদনশীল করতে পারি?

উদাহরণস্বরূপ, এখন এটি যেভাবে কাজ করে:

String target = "FooBar";
target.replace("Foo", "") // would return "Bar"

String target = "fooBar";
target.replace("Foo", "") // would return "fooBar"

আমি কীভাবে এটিকে এতটা প্রতিস্থাপন করতে পারি (বা যদি আরও উপযুক্ত পদ্ধতি রয়েছে) কেস-সংবেদনশীল যাতে উভয় উদাহরণ "বার" ফেরত দেয়?

উত্তর:


284
String target = "FOOBar";
target = target.replaceAll("(?i)foo", "");
System.out.println(target);

আউটপুট:

Bar

এটি উল্লেখ করার মতো যে replaceAllপ্রথম যুক্তিকে একটি রেজেক্স প্যাটার্ন হিসাবে বিবেচনা করে, যা অপ্রত্যাশিত ফলাফলের কারণ হতে পারে। এটি সমাধান করার জন্য, Pattern.quoteমন্তব্যে প্রস্তাবিত হিসাবে ব্যবহার করুন ।


1
যদি লক্ষ্যতে $ বা ডায়াক্রিটিক্যাল অক্ষর like এর মতো থাকে?
স্ট্র্যাকট্রেসার

3
আমার অর্থ দুটি জিনিস: 1. "bl 1.123" .replaceAll ("(? I) bláü") কোনও কিছুর প্রতিস্থাপন করে না। 2. "বাক্য! সমাপ্তি" .রেজল সমস্ত ("(? I) বাক্য।") সম্ভবত প্রত্যাশার চেয়ে বেশি প্রতিস্থাপন করে।
স্ট্র্যাকট্রেসার

1
স্ট্রিংটিকে এত সহজ ম্যাচিং করে রেজিজেসে রূপান্তর করতে পারবেন না। এটি সাধারণত সঠিক নয়, এটি কেবলমাত্র নির্দিষ্ট ক্ষেত্রে কাজ করবে।
ডানুবিয়ার নাবিক

19
সার্জ স্ট্রিংটিকে রেজেক্স হিসাবে ব্যাখ্যা করা থেকে রক্ষা করতে প্যাটার্ন.কোয়েট () ব্যবহার করুন। এই ডোটি snot উপরে উল্লিখিত ইউনিকোড quirks ঠিকানা, কিন্তু মৌলিক অক্ষর সেট জন্য ভাল হওয়া উচিত। যেমন target.replaceAll("(?i)"+Pattern.quote("foo"), "");
জেফ অ্যাডামসন

1
শুধু নিশ্চিত করছি. প্যাটার্ন.কোয়েট ("foo") প্রয়োজন নেই যদি স্ট্রিংটি "foo" ঠিক থাকে? কেবল যদি এটি আরও অভিনব কিছু হয়, তাই না?
এডি

10

আপনি যদি কেস সম্পর্কে চিন্তা না করেন তবে আপনার সমস্ত আপস ফিরে আসে কিনা তা আপনি সম্ভবত বিবেচনা করবেন না:

target.toUpperCase().replace("FOO", "");

যদি আপনার á এর মতো অক্ষরের সাথে লেনদেন করা হয় তবে আপনি লোকেলকে টুঅপারকেসে (লোকাল) পাস করতে পারেন á
লুঠ করুন

10

অন্যান্য পদ্ধতির মতো সম্ভবত মার্জিত নয় তবে এটি বেশ শক্ত এবং অনুসরণ করা সহজ, এসএসপি। জাভা আরও নতুন মানুষের জন্য। স্ট্রিং ক্লাস সম্পর্কে আমার কাছে যে জিনিসটি আসে তা হ'ল: এটি অনেক দিন ধরে ছিল এবং যখন এটি রেগ এক্সপ্লেসের সাথে একটি গ্লোবাল রিপ্লেস এবং স্ট্রিংসের সাথে একটি গ্লোবাল রিপ্লেস সমর্থন করে (চারসেকেন্সের মাধ্যমে), শেষটির কোনও সাধারণ বুলিয়ান প্যারামিটার নেই : 'isCaseInsensitive'। সত্যিই, আপনি ভেবেছিলেন যে কেবল একটি সামান্য সুইচ যুক্ত করে, এটির অনুপস্থিতির কারণ বিশেষত নবজাতকদের জন্য যে সমস্ত সমস্যা রয়েছে তা এড়ানো যেত। এখন জেডিকে on-এ, স্ট্রিং এখনও এই সামান্য সংযোজন সমর্থন করে না!

যাইহোক, আমি আঁকড়ে ধরা বন্ধ করব। জাভাতে বিশেষত প্রত্যেকের জন্য, আপনার কাট-পেস্ট ডিউস প্রাক্তন মেশিনা । যেমনটি আমি বলেছি, মার্জিত নয় এবং আপনাকে কোনও চটজলদি কোডিং পুরস্কার জিতবে না, তবে এটি কার্যকর এবং নির্ভরযোগ্য। কোন মন্তব্য, অবদান নির্দ্বিধায়। (হ্যাঁ, আমি জানি, স্ট্রিংবফার সম্ভবত দুটি চরিত্রের স্ট্রিং মিউটেশন লাইন পরিচালনা করার পক্ষে আরও ভাল পছন্দ, তবে কৌশলগুলি অদলবদল করার পক্ষে এটি যথেষ্ট সহজ))

public String replaceAll(String findtxt, String replacetxt, String str, 
        boolean isCaseInsensitive) {
    if (str == null) {
        return null;
    }
    if (findtxt == null || findtxt.length() == 0) {
        return str;
    }
    if (findtxt.length() > str.length()) {
        return str;
    }
    int counter = 0;
    String thesubstr = "";
    while ((counter < str.length()) 
            && (str.substring(counter).length() >= findtxt.length())) {
        thesubstr = str.substring(counter, counter + findtxt.length());
        if (isCaseInsensitive) {
            if (thesubstr.equalsIgnoreCase(findtxt)) {
                str = str.substring(0, counter) + replacetxt 
                    + str.substring(counter + findtxt.length());
                // Failing to increment counter by replacetxt.length() leaves you open
                // to an infinite-replacement loop scenario: Go to replace "a" with "aa" but
                // increment counter by only 1 and you'll be replacing 'a's forever.
                counter += replacetxt.length();
            } else {
                counter++; // No match so move on to the next character from
                           // which to check for a findtxt string match.
            }
        } else {
            if (thesubstr.equals(findtxt)) {
                str = str.substring(0, counter) + replacetxt 
                    + str.substring(counter + findtxt.length());
                counter += replacetxt.length();
            } else {
                counter++;
            }
        }
    }
    return str;
}

এই জটিলতাটি হ'ল ধীরে ধীরে এর জটিলতা হ'ল হ'ল (আকার_সৌ * * আকার_পদ্ধতি)
ম্লাদেন অ্যাডামোভিক

9

নিয়মিত এক্সপ্রেশনগুলি কিছু অক্ষর সংরক্ষিত থাকার কারণে পরিচালনা করতে বেশ জটিল: উদাহরণস্বরূপ, "foo.bar".replaceAll(".")একটি খালি স্ট্রিং তৈরি করে, কারণ বিন্দুটির অর্থ "কিছু" যদি আপনি কেবলমাত্র পয়েন্টটি প্রতিস্থাপন করতে চান তবে প্যারামিটার হিসাবে চিহ্নিত করা উচিত "\\."

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

public class LowerCaseReplace 
{
    public static String replace(String source, String target, String replacement)
    {
        StringBuilder sbSource = new StringBuilder(source);
        StringBuilder sbSourceLower = new StringBuilder(source.toLowerCase());
        String searchString = target.toLowerCase();

        int idx = 0;
        while((idx = sbSourceLower.indexOf(searchString, idx)) != -1) {
            sbSource.replace(idx, idx + searchString.length(), replacement);
            sbSourceLower.replace(idx, idx + searchString.length(), replacement);
            idx+= replacement.length();
        }
        sbSourceLower.setLength(0);
        sbSourceLower.trimToSize();
        sbSourceLower = null;

        return sbSource.toString();
    }


    public static void main(String[] args)
    {
        System.out.println(replace("xXXxyyyXxxuuuuoooo", "xx", "**"));
        System.out.println(replace("FOoBaR", "bar", "*"));
    }
}

1
দুর্দান্ত কাজ! নোট করুন যে "টার্গেট" অবশ্যই নালার হবে না। ক্লিয়ারিং sbSourceLower প্রয়োজন হবে না (আর কোনও)।
msteiger

সংক্ষিপ্ত সমাধানের জন্য ধন্যবাদ এবং সংশোধনের জন্য @ এমএসটিইগারকে ধন্যবাদ। আমি অবাক হই কেন কেউ গুয়ারা, অ্যাপাচি কমন্স ইত্যাদির মতো কোনও বিখ্যাত লাইবের অনুরূপ সমাধান কেন যোগ করলেন না?
yetanothercoder

4

অ-ইউনিকোড অক্ষরের জন্য:

String result = Pattern.compile("(?i)препарат", 
Pattern.UNICODE_CASE).matcher(source).replaceAll("БАД");

4

org.apache.commons.lang3.StringUtils:

পাবলিক স্ট্যাটিক স্ট্রিং রিপ্লেজআইগনোরকেস (স্ট্রিং টেক্সট, স্ট্রিং সার্চস্ট্রিং, স্ট্রিং রিপ্লেসমেন্ট)

কেস সংবেদনশীলভাবে অন্য একটি স্ট্রিংয়ের মধ্যে একটি স্ট্রিংয়ের সমস্ত উপস্থিতি প্রতিস্থাপন করে।


3

আমি চাই smas এর উত্তর যে ব্যবহারসমূহ replaceAllএকটি রেগুলার এক্সপ্রেশন সঙ্গে। আপনি যদি একই প্রতিস্থাপনটি অনেক বার করতে যাচ্ছেন তবে নিয়মিত ভাবটি একবার প্রি-কম্পাইল করে বোঝা যায়:

import java.util.regex.Pattern;

public class Test { 

    private static final Pattern fooPattern = Pattern.compile("(?i)foo");

    private static removeFoo(s){
        if (s != null) s = fooPattern.matcher(s).replaceAll("");
        return s;
    }

    public static void main(String[] args) {
        System.out.println(removeFoo("FOOBar"));
    }
}

3

তৃতীয় পক্ষের লাইব্রেরি ছাড়া এটি কেবল সহজ করুন:

    final String source = "FooBar";
    final String target = "Foo";
    final String replacement = "";
    final String result = Pattern.compile(target, Pattern.LITERAL | Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE).matcher(source)
.replaceAll(Matcher.quoteReplacement(replacement));
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.