আমি জাভা রেজেেক্সে গ্রুপগুলি প্রতিস্থাপন করতে পারি?


102

আমার এই কোডটি রয়েছে এবং আমি জানতে চাই, আমি জাভা রেজেজেলে কেবলমাত্র গোষ্ঠীগুলি (সমস্ত প্যাটার্ন নয়) প্রতিস্থাপন করতে পারি। কোড:

 //...
 Pattern p = Pattern.compile("(\\d).*(\\d)");
    String input = "6 example input 4";
    Matcher m = p.matcher(input);
    if (m.find()) {

        //Now I want replace group one ( (\\d) ) with number 
       //and group two (too (\\d) ) with 1, but I don't know how.

    }

6
আপনি কি নিজের প্রশ্নটি পরিষ্কার করতে পারেন, যেমন that ইনপুটটির জন্য প্রত্যাশিত আউটপুট দিতে পারেন?
মাইকেল মায়ার্স

উত্তর:


128

$nক্যাপচারিত উপ-অনুচ্ছেদগুলিতে উল্লেখ করতে (যেখানে এন একটি সংখ্যা রয়েছে) ব্যবহার করুন replaceFirst(...)। আমি ধরে নিচ্ছি আপনি প্রথম গ্রুপটির সাথে আক্ষরিক স্ট্রিং "নম্বর" এবং দ্বিতীয় গ্রুপটি প্রথম দলের মান দিয়ে প্রতিস্থাপন করতে চেয়েছিলেন ।

Pattern p = Pattern.compile("(\\d)(.*)(\\d)");
String input = "6 example input 4";
Matcher m = p.matcher(input);
if (m.find()) {
    // replace first number with "number" and second number with the first
    String output = m.replaceFirst("number $3$1");  // number 46
}

(\D+)পরিবর্তে দ্বিতীয় গ্রুপের জন্য বিবেচনা করুন (.*)*একটি লোভী ম্যাচার, এবং প্রথমে শেষ অঙ্কটি গ্রাস করবে। (\d)চূড়ান্ত অঙ্কের সাথে ম্যাচ করতে পারার আগে ম্যাচারকে বুঝতে হবে যে ফাইনালের সাথে ম্যাচ করার মতো কিছুই নেই।


7
ভাল হত যদি আপনি একটি উদাহরণ আউটপুট পোস্ট যেত
winklerrr

6
এটি প্রথম ম্যাচে কাজ করে, তবে যদি সেখানে অনেকগুলি গ্রুপ থাকে এবং আপনি কিছুক্ষণের সাথে তাদের উপর পুনরাবৃত্তি করেন তবে তা কাজ করবে না (এম.ফাইন্ড ())
হুগো জারাগোজা

4
আমি হুগোর সাথে একমত, সমাধানটি কার্যকর করার এটি একটি ভয়ানক উপায় ... কেন পৃথিবীতে এই স্বীকৃত উত্তর এবং এসিডকঞ্জিয়ারের উত্তর নয় - যা সঠিক সমাধান: সংখ্যার কোড, উচ্চ সংহতি এবং কম সংশ্লেষ, খুব কম সুযোগ (যদি কোনও সুযোগ না থাকে) অযাচিত পার্শ্ব প্রতিক্রিয়া ... দীর্ঘশ্বাস ...
ফায়ারলাইট

এই উত্তরটি বর্তমানে বৈধ নয়। হওয়া m.replaceFirst("number $2$1");উচিতm.replaceFirst("number $3$1");
ড্যানিয়েল আইজেনরিচ

56

আপনি জেনেরিক প্রতিস্থাপন পদ্ধতিটি ব্যবহার করতে Matcher#start(group)এবং Matcher#end(group)তৈরি করতে পারেন :

public static String replaceGroup(String regex, String source, int groupToReplace, String replacement) {
    return replaceGroup(regex, source, groupToReplace, 1, replacement);
}

public static String replaceGroup(String regex, String source, int groupToReplace, int groupOccurrence, String replacement) {
    Matcher m = Pattern.compile(regex).matcher(source);
    for (int i = 0; i < groupOccurrence; i++)
        if (!m.find()) return source; // pattern not met, may also throw an exception here
    return new StringBuilder(source).replace(m.start(groupToReplace), m.end(groupToReplace), replacement).toString();
}

public static void main(String[] args) {
    // replace with "%" what was matched by group 1 
    // input: aaa123ccc
    // output: %123ccc
    System.out.println(replaceGroup("([a-z]+)([0-9]+)([a-z]+)", "aaa123ccc", 1, "%"));

    // replace with "!!!" what was matched the 4th time by the group 2
    // input: a1b2c3d4e5
    // output: a1b2c3d!!!e5
    System.out.println(replaceGroup("([a-z])(\\d)", "a1b2c3d4e5", 2, 4, "!!!"));
}

এখানে অনলাইন ডেমো পরীক্ষা করুন


4
এটি সহীকরণের কোডটিতে সংযোগের এক স্তরের পরিচয় না দিয়েই এটি সর্বাধিক সম্পূর্ণ এবং "যেতে প্রস্তুত" সমাধানটির গ্রহণযোগ্য উত্তর হওয়া উচিত। যদিও আমি তাদের মধ্যে একটির নামের নাম পরিবর্তন করার পরামর্শ দেব। প্রথম নজরে এটি প্রথম পদ্ধতিতে পুনরাবৃত্ত কল বলে মনে হচ্ছে।
ফায়ারলাইট

মিস করার সুযোগটি মিস করেছেন। পুনরাবৃত্তির কল সম্পর্কে অংশটি ফিরিয়ে নিন, কোডটি সঠিকভাবে বিশ্লেষণ করলেন না। ওভারলোডগুলি একসাথে ভালভাবে কাজ করে
ফায়ারলাইট

এই সমাধানটি কেবলমাত্র একক ঘটনা এবং একটি গোষ্ঠী প্রতিস্থাপনের জন্য উপযুক্ত এবং প্রতিটি প্রতিস্থাপনের সাথে সম্পূর্ণ স্ট্রিং অনুলিপি করার কারণে অন্য কোনও কারণে অত্যন্ত সাব-আপ্টিমাল হবে। তবে এটি একটি ভাল সূচনা পয়েন্ট। একটি করুণ জাভা হ'ল প্রচুর বোকা, তবে মৌলিক স্ট্রিং ম্যানিপুলেশন সুবিধার অভাব রয়েছে।
9 ইএসডিএক্স 9 আরভিজে 0lo

24

একটি মৃত ঘোড়াটিকে পেটানোর জন্য দুঃখিত, তবে এটি একপ্রকার অদ্ভুত যে কেউই এটিকে নির্দেশ করেনি - "হ্যাঁ আপনি পারেন তবে এটি বাস্তব জীবনে আপনি কীভাবে দলগুলিকে বন্দী করে রাখছেন তার বিপরীত"।

আপনি যদি রেজেক্সকে যেভাবে ব্যবহার করতে চান সেভাবে ব্যবহার করেন, সমাধানটি এর মতোই সহজ:

"6 example input 4".replaceAll("(?:\\d)(.*)(?:\\d)", "number$11");

বা নীচে shmosel দ্বারা যথাযথভাবে নির্দেশিত,

"6 example input 4".replaceAll("\d(.*)\d", "number$11");

... যেহেতু আপনার রেজেক্সে দশমিকগুলি মোটেও গ্রুপ করার কোনও ভাল কারণ নেই।

আপনি যে স্ট্রিংটি ফেলে দিতে চান সেই অংশগুলিতে আপনি সাধারণত ক্যাপচারিং গ্রুপ ব্যবহার করবেন না , আপনি যে স্ট্রিংটি রাখতে চান তার অংশে ব্যবহার করুন

আপনি যদি সত্যিই এমন গ্রুপগুলি চান যা আপনি প্রতিস্থাপন করতে চান তবে আপনি সম্ভবত এটির বদলে যা চান সেটি হ'ল টেম্প্লেটিং ইঞ্জিন (যেমন গোঁফ, ইজেস, স্ট্রিংটেম্পলেট, ...)।


কৌতূহলীদের একপাশে, এমনকি রেজেক্সগুলিতে নন-ক্যাপচারিং গোষ্ঠীগুলি ঠিক সেখানে রয়েছে যে রেজেক্স ইঞ্জিনটি ভেরিয়েবল পাঠ্যকে সনাক্ত করতে এবং এড়াতে তাদের প্রয়োজন। উদাহরণস্বরূপ, ইন

(?:abc)*(capture me)(?:bcd)*

আপনি তাদের প্রয়োজন হলে আপনার ইনপুট হয় "abcabc মত সন্ধান করতে পারেন ক্যাপচার আমাকে bcdbcd" বা "এবিসি ক্যাপচার আমাকে BCD" বা এমনকি শুধু "আমাকে ক্যাপচার"।

বা এটিকে অন্য উপায়ে রাখতে: পাঠ্যটি যদি সর্বদা একই থাকে এবং আপনি এটি ক্যাপচার না করেন তবে গোষ্ঠীগুলি ব্যবহার করার কোনও কারণ নেই।


4
ক্যাপচারকারী দলগুলি অপ্রয়োজনীয়; \d(.*)\dযথেষ্ট হবে.
shmosel

4
আমি $11এখানে বুঝতে পারি না । 11 কেন?
অ্যালেক্সিস

4
@ অ্যালেক্সিস - এটি একটি জাভা রেজেক্স কিরক: যদি গ্রুপ 11 সেট করা না থাকে তবে জাভা 11 ডলারকে 1 ডলার হিসাবে ব্যাখ্যা করে 1 টি অনুসরণ করবে
ইয়ারো

9

চারদিকে পেরেন যোগ করে তৃতীয় গোষ্ঠী যুক্ত করুন .*, তারপরে অনুবর্তনটি এর সাথে প্রতিস্থাপন করুন "number" + m.group(2) + "1"। যেমন:

String output = m.replaceFirst("number" + m.group(2) + "1");

4
প্রকৃতপক্ষে, ম্যাচার রেফারেন্সের style 2 শৈলীর সমর্থন করে, তাই m.replaceFrst ("সংখ্যা $ 21") একই কাজ করবে।
মাইকেল মায়ার্স

আসলে, তারা তারা না একই জিনিস করে। "number$21"কাজ করে এবং "number" + m.group(2) + "1"না।
অ্যালান মুর

4
দেখে মনে হচ্ছে number$2121 গোষ্ঠীটি প্রতিস্থাপন করবে, গ্রুপ 2 + স্ট্রিং "1" নয়।
ফার্নান্দো এম

এটি কি সরল স্ট্রিং কনটেনটেশন, তাই না? কেন আমাদের রিপ্লেসফার্সকে একেবারে কল করা দরকার?
Zxcv Mnb

2

গ্রুপ পজিশনগুলি পেতে আপনি ম্যাচার.স্টার্ট () এবং ম্যাচার.এন্ড () পদ্ধতি ব্যবহার করতে পারেন। সুতরাং এই অবস্থানগুলি ব্যবহার করে আপনি যে কোনও পাঠ্য সহজেই প্রতিস্থাপন করতে পারেন।


2

ইনপুট থেকে পাসওয়ার্ড ক্ষেত্রগুলি প্রতিস্থাপন করুন:

{"_csrf":["9d90c85f-ac73-4b15-ad08-ebaa3fa4a005"],"originPassword":["uaas"],"newPassword":["uaas"],"confirmPassword":["uaas"]}



  private static final Pattern PATTERN = Pattern.compile(".*?password.*?\":\\[\"(.*?)\"\\](,\"|}$)", Pattern.CASE_INSENSITIVE);

  private static String replacePassword(String input, String replacement) {
    Matcher m = PATTERN.matcher(input);
    StringBuffer sb = new StringBuffer();
    while (m.find()) {
      Matcher m2 = PATTERN.matcher(m.group(0));
      if (m2.find()) {
        StringBuilder stringBuilder = new StringBuilder(m2.group(0));
        String result = stringBuilder.replace(m2.start(1), m2.end(1), replacement).toString();
        m.appendReplacement(sb, result);
      }
    }
    m.appendTail(sb);
    return sb.toString();
  }

  @Test
  public void test1() {
    String input = "{\"_csrf\":[\"9d90c85f-ac73-4b15-ad08-ebaa3fa4a005\"],\"originPassword\":[\"123\"],\"newPassword\":[\"456\"],\"confirmPassword\":[\"456\"]}";
    String expected = "{\"_csrf\":[\"9d90c85f-ac73-4b15-ad08-ebaa3fa4a005\"],\"originPassword\":[\"**\"],\"newPassword\":[\"**\"],\"confirmPassword\":[\"**\"]}";
    Assert.assertEquals(expected, replacePassword(input, "**"));
  }

1

এখানে একটি পৃথক সমাধান, এটি একাধিক ম্যাচে একক গ্রুপের প্রতিস্থাপনের অনুমতি দেয়। এটি এক্সিকিউশন অর্ডারকে বিপরীত করতে স্ট্যাক ব্যবহার করে, সুতরাং স্ট্রিং অপারেশনটি নিরাপদে সম্পাদন করা যায়।

private static void demo () {

    final String sourceString = "hello world!";

    final String regex = "(hello) (world)(!)";
    final Pattern pattern = Pattern.compile(regex);

    String result = replaceTextOfMatchGroup(sourceString, pattern, 2, world -> world.toUpperCase());
    System.out.println(result);  // output: hello WORLD!
}

public static String replaceTextOfMatchGroup(String sourceString, Pattern pattern, int groupToReplace, Function<String,String> replaceStrategy) {
    Stack<Integer> startPositions = new Stack<>();
    Stack<Integer> endPositions = new Stack<>();
    Matcher matcher = pattern.matcher(sourceString);

    while (matcher.find()) {
        startPositions.push(matcher.start(groupToReplace));
        endPositions.push(matcher.end(groupToReplace));
    }
    StringBuilder sb = new StringBuilder(sourceString);
    while (! startPositions.isEmpty()) {
        int start = startPositions.pop();
        int end = endPositions.pop();
        if (start >= 0 && end >= 0) {
            sb.replace(start, end, replaceStrategy.apply(sourceString.substring(start, end)));
        }
    }
    return sb.toString();       
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.