javaregexreplaceregex-group

Can I replace groups in Java regex?


I have this code, and I want to know, if I can replace only groups (not all pattern) in Java regex. Code:

 //...
 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.

    }

Solution

  • Use $n (where n is a digit) to refer to captured subsequences in replaceFirst(...). I'm assuming you wanted to replace the first group with the literal string "number" and the second group with the value of the first group.

    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
        // the added group ("(.*)" which is $2) captures unmodified text to include it in the result
        String output = m.replaceFirst("number$2$1"); // "number example input 6"
    }
    

    Consider (\D+) for the second group instead of (.*). * is a greedy matcher, and will at first consume the last digit. The matcher will then have to backtrack when it realizes the final (\d) has nothing to match, before it can match to the final digit.

    Edit

    Years later, this still gets votes, and the comments and edits (which broke the answer) show there is still confusion on what the question meant. I've fixed it, and added the much needed example output.

    The edits to the replacement (some thought $2 should not be used) actually broke the answer. Though the continued votes shows the answer hits the key point - Use $n references within replaceFirst(...) to reuse captured values - the edits lost the fact that unmodified text needs to be captured as well, and used in the replacement so that "only groups (not all pattern)".

    The question, and thus this answer, is not concerned with iterating. This is intentionally an MRE.