Can I replace groups in Java regex?












79















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.

}









share|improve this question




















  • 5





    Can you clarify your question, like maybe give the expected output for that input?

    – Michael Myers
    Jun 12 '09 at 20:12
















79















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.

}









share|improve this question




















  • 5





    Can you clarify your question, like maybe give the expected output for that input?

    – Michael Myers
    Jun 12 '09 at 20:12














79












79








79


12






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.

}









share|improve this question
















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.

}






java regex replace regex-group






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 21 '17 at 6:45









ekad

12.2k123742




12.2k123742










asked Jun 12 '09 at 19:39









wokenawokena

26621017




26621017








  • 5





    Can you clarify your question, like maybe give the expected output for that input?

    – Michael Myers
    Jun 12 '09 at 20:12














  • 5





    Can you clarify your question, like maybe give the expected output for that input?

    – Michael Myers
    Jun 12 '09 at 20:12








5




5





Can you clarify your question, like maybe give the expected output for that input?

– Michael Myers
Jun 12 '09 at 20:12





Can you clarify your question, like maybe give the expected output for that input?

– Michael Myers
Jun 12 '09 at 20:12












7 Answers
7






active

oldest

votes


















103














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
String output = m.replaceFirst("number $3$1"); // number 46
}


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.






share|improve this answer





















  • 7





    Would have been nice if you would have posted an example output

    – winklerrr
    Aug 25 '15 at 10:33






  • 6





    This works on the first match, but wont work if there are many groups and you are iterating over them with a while(m.find())

    – Hugo Zaragoza
    Jan 3 '16 at 21:50






  • 1





    I Agree with Hugo, this is a terrible way to implement the solution... Why on Earth is this the accepted answer and not acdcjunior's answer - which is the perfect solution: small amount of code, high cohesion and low coupling, much less chance (if not no chance) of unwanted side effects... sigh...

    – FireLight
    Jun 11 '17 at 9:07













  • @Wrap2Win Why didn’t you down vote this? ;)

    – ᴠɪɴᴄᴇɴᴛ
    Sep 4 '17 at 14:50











  • This answer is currently not valid. The m.replaceFirst("number $2$1"); should be m.replaceFirst("number $3$1");

    – Daniel Eisenreich
    Jan 10 '18 at 9:30



















44














You could use Matcher#start(group) and Matcher#end(group) to build a generic replacement method:



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, "!!!"));
}


Check online demo here.






share|improve this answer



















  • 1





    This really should be the accepted answer it's the most complete and "ready to go" solution without introducing a level of coupling to the accompanying code. Although I would recommend changing the method names of one of those. At first glance it looks like a recursive call in the first method.

    – FireLight
    Jun 11 '17 at 9:09













  • Missed edit opportunity. Take back the part about the recursive call, didn't analyse the code properly. The overloads work well together

    – FireLight
    Jun 11 '17 at 9:56



















9














Add a third group by adding parens around .*, then replace the subsequence with "number" + m.group(2) + "1". e.g.:



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





share|improve this answer





















  • 4





    Actually, Matcher supports the $2 style of reference, so m.replaceFirst("number$21") would do the same thing.

    – Michael Myers
    Jun 12 '09 at 19:53











  • Actually, they they don't do the same thing. "number$21" works and "number" + m.group(2) + "1" doesn't.

    – Alan Moore
    Jan 7 '14 at 21:29






  • 2





    It looks like number$21 would replace group 21, not group 2 + the string "1".

    – Fernando M. Pinheiro
    Mar 14 '14 at 13:50











  • This is plain string concatenation, right ? why do we need to call replaceFirst at all ?

    – Zxcv Mnb
    Aug 13 '15 at 20:02





















8














Sorry to beat a dead horse, but it is kind-of weird that no-one pointed this out - "Yes you can, but this is the opposite of how you use capturing groups in real life".



If you use Regex the way it is meant to be used, the solution is as simple as this:



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


Or as rightfully pointed out by shmosel below,



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


...since in your regex there is no good reason to group the decimals at all.



You don't usually use capturing groups on the parts of the string you want to discard, you use them on the part of the string you want to keep.



If you really want groups that you want to replace, what you probably want instead is a templating engine (e.g. moustache, ejs, StringTemplate, ...).





As an aside for the curious, even non-capturing groups in regexes are just there for the case that the regex engine needs them to recognize and skip variable text. For example, in



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


you need them if your input can look either like "abcabccapture mebcdbcd" or "abccapture mebcd" or even just "capture me".



Or to put it the other way around: if the text is always the same, and you don't capture it, there is no reason to use groups at all.






share|improve this answer





















  • 1





    The non-capturing groups are unnecessary; d(.*)d will suffice.

    – shmosel
    Feb 28 '18 at 8:34





















1














You can use matcher.start() and matcher.end() methods to get the group positions. So using this positions you can easily replace any text.






share|improve this answer































    0














    Here is a different solution, that also allows the replacement of a single group in multiple matches.
    It uses stacks to reverse the execution order, so the string operation can be safely executed.



    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();
    }





    share|improve this answer

































      0














      replace the password fields from the input:



      {"_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, "**"));
      }





      share|improve this answer

























        Your Answer






        StackExchange.ifUsing("editor", function () {
        StackExchange.using("externalEditor", function () {
        StackExchange.using("snippets", function () {
        StackExchange.snippets.init();
        });
        });
        }, "code-snippets");

        StackExchange.ready(function() {
        var channelOptions = {
        tags: "".split(" "),
        id: "1"
        };
        initTagRenderer("".split(" "), "".split(" "), channelOptions);

        StackExchange.using("externalEditor", function() {
        // Have to fire editor after snippets, if snippets enabled
        if (StackExchange.settings.snippets.snippetsEnabled) {
        StackExchange.using("snippets", function() {
        createEditor();
        });
        }
        else {
        createEditor();
        }
        });

        function createEditor() {
        StackExchange.prepareEditor({
        heartbeatType: 'answer',
        autoActivateHeartbeat: false,
        convertImagesToLinks: true,
        noModals: true,
        showLowRepImageUploadWarning: true,
        reputationToPostImages: 10,
        bindNavPrevention: true,
        postfix: "",
        imageUploader: {
        brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
        contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
        allowUrls: true
        },
        onDemand: true,
        discardSelector: ".discard-answer"
        ,immediatelyShowMarkdownHelp:true
        });


        }
        });














        draft saved

        draft discarded


















        StackExchange.ready(
        function () {
        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f988655%2fcan-i-replace-groups-in-java-regex%23new-answer', 'question_page');
        }
        );

        Post as a guest















        Required, but never shown

























        7 Answers
        7






        active

        oldest

        votes








        7 Answers
        7






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes









        103














        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
        String output = m.replaceFirst("number $3$1"); // number 46
        }


        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.






        share|improve this answer





















        • 7





          Would have been nice if you would have posted an example output

          – winklerrr
          Aug 25 '15 at 10:33






        • 6





          This works on the first match, but wont work if there are many groups and you are iterating over them with a while(m.find())

          – Hugo Zaragoza
          Jan 3 '16 at 21:50






        • 1





          I Agree with Hugo, this is a terrible way to implement the solution... Why on Earth is this the accepted answer and not acdcjunior's answer - which is the perfect solution: small amount of code, high cohesion and low coupling, much less chance (if not no chance) of unwanted side effects... sigh...

          – FireLight
          Jun 11 '17 at 9:07













        • @Wrap2Win Why didn’t you down vote this? ;)

          – ᴠɪɴᴄᴇɴᴛ
          Sep 4 '17 at 14:50











        • This answer is currently not valid. The m.replaceFirst("number $2$1"); should be m.replaceFirst("number $3$1");

          – Daniel Eisenreich
          Jan 10 '18 at 9:30
















        103














        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
        String output = m.replaceFirst("number $3$1"); // number 46
        }


        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.






        share|improve this answer





















        • 7





          Would have been nice if you would have posted an example output

          – winklerrr
          Aug 25 '15 at 10:33






        • 6





          This works on the first match, but wont work if there are many groups and you are iterating over them with a while(m.find())

          – Hugo Zaragoza
          Jan 3 '16 at 21:50






        • 1





          I Agree with Hugo, this is a terrible way to implement the solution... Why on Earth is this the accepted answer and not acdcjunior's answer - which is the perfect solution: small amount of code, high cohesion and low coupling, much less chance (if not no chance) of unwanted side effects... sigh...

          – FireLight
          Jun 11 '17 at 9:07













        • @Wrap2Win Why didn’t you down vote this? ;)

          – ᴠɪɴᴄᴇɴᴛ
          Sep 4 '17 at 14:50











        • This answer is currently not valid. The m.replaceFirst("number $2$1"); should be m.replaceFirst("number $3$1");

          – Daniel Eisenreich
          Jan 10 '18 at 9:30














        103












        103








        103







        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
        String output = m.replaceFirst("number $3$1"); // number 46
        }


        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.






        share|improve this answer















        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
        String output = m.replaceFirst("number $3$1"); // number 46
        }


        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.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Jan 10 '18 at 10:03









        Daniel Eisenreich

        5811521




        5811521










        answered Jun 12 '09 at 20:05









        ChadwickChadwick

        10.5k74365




        10.5k74365








        • 7





          Would have been nice if you would have posted an example output

          – winklerrr
          Aug 25 '15 at 10:33






        • 6





          This works on the first match, but wont work if there are many groups and you are iterating over them with a while(m.find())

          – Hugo Zaragoza
          Jan 3 '16 at 21:50






        • 1





          I Agree with Hugo, this is a terrible way to implement the solution... Why on Earth is this the accepted answer and not acdcjunior's answer - which is the perfect solution: small amount of code, high cohesion and low coupling, much less chance (if not no chance) of unwanted side effects... sigh...

          – FireLight
          Jun 11 '17 at 9:07













        • @Wrap2Win Why didn’t you down vote this? ;)

          – ᴠɪɴᴄᴇɴᴛ
          Sep 4 '17 at 14:50











        • This answer is currently not valid. The m.replaceFirst("number $2$1"); should be m.replaceFirst("number $3$1");

          – Daniel Eisenreich
          Jan 10 '18 at 9:30














        • 7





          Would have been nice if you would have posted an example output

          – winklerrr
          Aug 25 '15 at 10:33






        • 6





          This works on the first match, but wont work if there are many groups and you are iterating over them with a while(m.find())

          – Hugo Zaragoza
          Jan 3 '16 at 21:50






        • 1





          I Agree with Hugo, this is a terrible way to implement the solution... Why on Earth is this the accepted answer and not acdcjunior's answer - which is the perfect solution: small amount of code, high cohesion and low coupling, much less chance (if not no chance) of unwanted side effects... sigh...

          – FireLight
          Jun 11 '17 at 9:07













        • @Wrap2Win Why didn’t you down vote this? ;)

          – ᴠɪɴᴄᴇɴᴛ
          Sep 4 '17 at 14:50











        • This answer is currently not valid. The m.replaceFirst("number $2$1"); should be m.replaceFirst("number $3$1");

          – Daniel Eisenreich
          Jan 10 '18 at 9:30








        7




        7





        Would have been nice if you would have posted an example output

        – winklerrr
        Aug 25 '15 at 10:33





        Would have been nice if you would have posted an example output

        – winklerrr
        Aug 25 '15 at 10:33




        6




        6





        This works on the first match, but wont work if there are many groups and you are iterating over them with a while(m.find())

        – Hugo Zaragoza
        Jan 3 '16 at 21:50





        This works on the first match, but wont work if there are many groups and you are iterating over them with a while(m.find())

        – Hugo Zaragoza
        Jan 3 '16 at 21:50




        1




        1





        I Agree with Hugo, this is a terrible way to implement the solution... Why on Earth is this the accepted answer and not acdcjunior's answer - which is the perfect solution: small amount of code, high cohesion and low coupling, much less chance (if not no chance) of unwanted side effects... sigh...

        – FireLight
        Jun 11 '17 at 9:07







        I Agree with Hugo, this is a terrible way to implement the solution... Why on Earth is this the accepted answer and not acdcjunior's answer - which is the perfect solution: small amount of code, high cohesion and low coupling, much less chance (if not no chance) of unwanted side effects... sigh...

        – FireLight
        Jun 11 '17 at 9:07















        @Wrap2Win Why didn’t you down vote this? ;)

        – ᴠɪɴᴄᴇɴᴛ
        Sep 4 '17 at 14:50





        @Wrap2Win Why didn’t you down vote this? ;)

        – ᴠɪɴᴄᴇɴᴛ
        Sep 4 '17 at 14:50













        This answer is currently not valid. The m.replaceFirst("number $2$1"); should be m.replaceFirst("number $3$1");

        – Daniel Eisenreich
        Jan 10 '18 at 9:30





        This answer is currently not valid. The m.replaceFirst("number $2$1"); should be m.replaceFirst("number $3$1");

        – Daniel Eisenreich
        Jan 10 '18 at 9:30













        44














        You could use Matcher#start(group) and Matcher#end(group) to build a generic replacement method:



        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, "!!!"));
        }


        Check online demo here.






        share|improve this answer



















        • 1





          This really should be the accepted answer it's the most complete and "ready to go" solution without introducing a level of coupling to the accompanying code. Although I would recommend changing the method names of one of those. At first glance it looks like a recursive call in the first method.

          – FireLight
          Jun 11 '17 at 9:09













        • Missed edit opportunity. Take back the part about the recursive call, didn't analyse the code properly. The overloads work well together

          – FireLight
          Jun 11 '17 at 9:56
















        44














        You could use Matcher#start(group) and Matcher#end(group) to build a generic replacement method:



        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, "!!!"));
        }


        Check online demo here.






        share|improve this answer



















        • 1





          This really should be the accepted answer it's the most complete and "ready to go" solution without introducing a level of coupling to the accompanying code. Although I would recommend changing the method names of one of those. At first glance it looks like a recursive call in the first method.

          – FireLight
          Jun 11 '17 at 9:09













        • Missed edit opportunity. Take back the part about the recursive call, didn't analyse the code properly. The overloads work well together

          – FireLight
          Jun 11 '17 at 9:56














        44












        44








        44







        You could use Matcher#start(group) and Matcher#end(group) to build a generic replacement method:



        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, "!!!"));
        }


        Check online demo here.






        share|improve this answer













        You could use Matcher#start(group) and Matcher#end(group) to build a generic replacement method:



        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, "!!!"));
        }


        Check online demo here.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Jan 8 '14 at 15:13









        acdcjunioracdcjunior

        82.6k22194194




        82.6k22194194








        • 1





          This really should be the accepted answer it's the most complete and "ready to go" solution without introducing a level of coupling to the accompanying code. Although I would recommend changing the method names of one of those. At first glance it looks like a recursive call in the first method.

          – FireLight
          Jun 11 '17 at 9:09













        • Missed edit opportunity. Take back the part about the recursive call, didn't analyse the code properly. The overloads work well together

          – FireLight
          Jun 11 '17 at 9:56














        • 1





          This really should be the accepted answer it's the most complete and "ready to go" solution without introducing a level of coupling to the accompanying code. Although I would recommend changing the method names of one of those. At first glance it looks like a recursive call in the first method.

          – FireLight
          Jun 11 '17 at 9:09













        • Missed edit opportunity. Take back the part about the recursive call, didn't analyse the code properly. The overloads work well together

          – FireLight
          Jun 11 '17 at 9:56








        1




        1





        This really should be the accepted answer it's the most complete and "ready to go" solution without introducing a level of coupling to the accompanying code. Although I would recommend changing the method names of one of those. At first glance it looks like a recursive call in the first method.

        – FireLight
        Jun 11 '17 at 9:09







        This really should be the accepted answer it's the most complete and "ready to go" solution without introducing a level of coupling to the accompanying code. Although I would recommend changing the method names of one of those. At first glance it looks like a recursive call in the first method.

        – FireLight
        Jun 11 '17 at 9:09















        Missed edit opportunity. Take back the part about the recursive call, didn't analyse the code properly. The overloads work well together

        – FireLight
        Jun 11 '17 at 9:56





        Missed edit opportunity. Take back the part about the recursive call, didn't analyse the code properly. The overloads work well together

        – FireLight
        Jun 11 '17 at 9:56











        9














        Add a third group by adding parens around .*, then replace the subsequence with "number" + m.group(2) + "1". e.g.:



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





        share|improve this answer





















        • 4





          Actually, Matcher supports the $2 style of reference, so m.replaceFirst("number$21") would do the same thing.

          – Michael Myers
          Jun 12 '09 at 19:53











        • Actually, they they don't do the same thing. "number$21" works and "number" + m.group(2) + "1" doesn't.

          – Alan Moore
          Jan 7 '14 at 21:29






        • 2





          It looks like number$21 would replace group 21, not group 2 + the string "1".

          – Fernando M. Pinheiro
          Mar 14 '14 at 13:50











        • This is plain string concatenation, right ? why do we need to call replaceFirst at all ?

          – Zxcv Mnb
          Aug 13 '15 at 20:02


















        9














        Add a third group by adding parens around .*, then replace the subsequence with "number" + m.group(2) + "1". e.g.:



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





        share|improve this answer





















        • 4





          Actually, Matcher supports the $2 style of reference, so m.replaceFirst("number$21") would do the same thing.

          – Michael Myers
          Jun 12 '09 at 19:53











        • Actually, they they don't do the same thing. "number$21" works and "number" + m.group(2) + "1" doesn't.

          – Alan Moore
          Jan 7 '14 at 21:29






        • 2





          It looks like number$21 would replace group 21, not group 2 + the string "1".

          – Fernando M. Pinheiro
          Mar 14 '14 at 13:50











        • This is plain string concatenation, right ? why do we need to call replaceFirst at all ?

          – Zxcv Mnb
          Aug 13 '15 at 20:02
















        9












        9








        9







        Add a third group by adding parens around .*, then replace the subsequence with "number" + m.group(2) + "1". e.g.:



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





        share|improve this answer















        Add a third group by adding parens around .*, then replace the subsequence with "number" + m.group(2) + "1". e.g.:



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






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Aug 15 '15 at 15:23

























        answered Jun 12 '09 at 19:47









        mkbmkb

        11k12246




        11k12246








        • 4





          Actually, Matcher supports the $2 style of reference, so m.replaceFirst("number$21") would do the same thing.

          – Michael Myers
          Jun 12 '09 at 19:53











        • Actually, they they don't do the same thing. "number$21" works and "number" + m.group(2) + "1" doesn't.

          – Alan Moore
          Jan 7 '14 at 21:29






        • 2





          It looks like number$21 would replace group 21, not group 2 + the string "1".

          – Fernando M. Pinheiro
          Mar 14 '14 at 13:50











        • This is plain string concatenation, right ? why do we need to call replaceFirst at all ?

          – Zxcv Mnb
          Aug 13 '15 at 20:02
















        • 4





          Actually, Matcher supports the $2 style of reference, so m.replaceFirst("number$21") would do the same thing.

          – Michael Myers
          Jun 12 '09 at 19:53











        • Actually, they they don't do the same thing. "number$21" works and "number" + m.group(2) + "1" doesn't.

          – Alan Moore
          Jan 7 '14 at 21:29






        • 2





          It looks like number$21 would replace group 21, not group 2 + the string "1".

          – Fernando M. Pinheiro
          Mar 14 '14 at 13:50











        • This is plain string concatenation, right ? why do we need to call replaceFirst at all ?

          – Zxcv Mnb
          Aug 13 '15 at 20:02










        4




        4





        Actually, Matcher supports the $2 style of reference, so m.replaceFirst("number$21") would do the same thing.

        – Michael Myers
        Jun 12 '09 at 19:53





        Actually, Matcher supports the $2 style of reference, so m.replaceFirst("number$21") would do the same thing.

        – Michael Myers
        Jun 12 '09 at 19:53













        Actually, they they don't do the same thing. "number$21" works and "number" + m.group(2) + "1" doesn't.

        – Alan Moore
        Jan 7 '14 at 21:29





        Actually, they they don't do the same thing. "number$21" works and "number" + m.group(2) + "1" doesn't.

        – Alan Moore
        Jan 7 '14 at 21:29




        2




        2





        It looks like number$21 would replace group 21, not group 2 + the string "1".

        – Fernando M. Pinheiro
        Mar 14 '14 at 13:50





        It looks like number$21 would replace group 21, not group 2 + the string "1".

        – Fernando M. Pinheiro
        Mar 14 '14 at 13:50













        This is plain string concatenation, right ? why do we need to call replaceFirst at all ?

        – Zxcv Mnb
        Aug 13 '15 at 20:02







        This is plain string concatenation, right ? why do we need to call replaceFirst at all ?

        – Zxcv Mnb
        Aug 13 '15 at 20:02













        8














        Sorry to beat a dead horse, but it is kind-of weird that no-one pointed this out - "Yes you can, but this is the opposite of how you use capturing groups in real life".



        If you use Regex the way it is meant to be used, the solution is as simple as this:



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


        Or as rightfully pointed out by shmosel below,



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


        ...since in your regex there is no good reason to group the decimals at all.



        You don't usually use capturing groups on the parts of the string you want to discard, you use them on the part of the string you want to keep.



        If you really want groups that you want to replace, what you probably want instead is a templating engine (e.g. moustache, ejs, StringTemplate, ...).





        As an aside for the curious, even non-capturing groups in regexes are just there for the case that the regex engine needs them to recognize and skip variable text. For example, in



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


        you need them if your input can look either like "abcabccapture mebcdbcd" or "abccapture mebcd" or even just "capture me".



        Or to put it the other way around: if the text is always the same, and you don't capture it, there is no reason to use groups at all.






        share|improve this answer





















        • 1





          The non-capturing groups are unnecessary; d(.*)d will suffice.

          – shmosel
          Feb 28 '18 at 8:34


















        8














        Sorry to beat a dead horse, but it is kind-of weird that no-one pointed this out - "Yes you can, but this is the opposite of how you use capturing groups in real life".



        If you use Regex the way it is meant to be used, the solution is as simple as this:



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


        Or as rightfully pointed out by shmosel below,



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


        ...since in your regex there is no good reason to group the decimals at all.



        You don't usually use capturing groups on the parts of the string you want to discard, you use them on the part of the string you want to keep.



        If you really want groups that you want to replace, what you probably want instead is a templating engine (e.g. moustache, ejs, StringTemplate, ...).





        As an aside for the curious, even non-capturing groups in regexes are just there for the case that the regex engine needs them to recognize and skip variable text. For example, in



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


        you need them if your input can look either like "abcabccapture mebcdbcd" or "abccapture mebcd" or even just "capture me".



        Or to put it the other way around: if the text is always the same, and you don't capture it, there is no reason to use groups at all.






        share|improve this answer





















        • 1





          The non-capturing groups are unnecessary; d(.*)d will suffice.

          – shmosel
          Feb 28 '18 at 8:34
















        8












        8








        8







        Sorry to beat a dead horse, but it is kind-of weird that no-one pointed this out - "Yes you can, but this is the opposite of how you use capturing groups in real life".



        If you use Regex the way it is meant to be used, the solution is as simple as this:



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


        Or as rightfully pointed out by shmosel below,



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


        ...since in your regex there is no good reason to group the decimals at all.



        You don't usually use capturing groups on the parts of the string you want to discard, you use them on the part of the string you want to keep.



        If you really want groups that you want to replace, what you probably want instead is a templating engine (e.g. moustache, ejs, StringTemplate, ...).





        As an aside for the curious, even non-capturing groups in regexes are just there for the case that the regex engine needs them to recognize and skip variable text. For example, in



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


        you need them if your input can look either like "abcabccapture mebcdbcd" or "abccapture mebcd" or even just "capture me".



        Or to put it the other way around: if the text is always the same, and you don't capture it, there is no reason to use groups at all.






        share|improve this answer















        Sorry to beat a dead horse, but it is kind-of weird that no-one pointed this out - "Yes you can, but this is the opposite of how you use capturing groups in real life".



        If you use Regex the way it is meant to be used, the solution is as simple as this:



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


        Or as rightfully pointed out by shmosel below,



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


        ...since in your regex there is no good reason to group the decimals at all.



        You don't usually use capturing groups on the parts of the string you want to discard, you use them on the part of the string you want to keep.



        If you really want groups that you want to replace, what you probably want instead is a templating engine (e.g. moustache, ejs, StringTemplate, ...).





        As an aside for the curious, even non-capturing groups in regexes are just there for the case that the regex engine needs them to recognize and skip variable text. For example, in



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


        you need them if your input can look either like "abcabccapture mebcdbcd" or "abccapture mebcd" or even just "capture me".



        Or to put it the other way around: if the text is always the same, and you don't capture it, there is no reason to use groups at all.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Mar 19 '18 at 10:31

























        answered Feb 28 '18 at 8:22









        YaroYaro

        30326




        30326








        • 1





          The non-capturing groups are unnecessary; d(.*)d will suffice.

          – shmosel
          Feb 28 '18 at 8:34
















        • 1





          The non-capturing groups are unnecessary; d(.*)d will suffice.

          – shmosel
          Feb 28 '18 at 8:34










        1




        1





        The non-capturing groups are unnecessary; d(.*)d will suffice.

        – shmosel
        Feb 28 '18 at 8:34







        The non-capturing groups are unnecessary; d(.*)d will suffice.

        – shmosel
        Feb 28 '18 at 8:34













        1














        You can use matcher.start() and matcher.end() methods to get the group positions. So using this positions you can easily replace any text.






        share|improve this answer




























          1














          You can use matcher.start() and matcher.end() methods to get the group positions. So using this positions you can easily replace any text.






          share|improve this answer


























            1












            1








            1







            You can use matcher.start() and matcher.end() methods to get the group positions. So using this positions you can easily replace any text.






            share|improve this answer













            You can use matcher.start() and matcher.end() methods to get the group positions. So using this positions you can easily replace any text.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Jun 9 '10 at 14:13









            ydannegydanneg

            513




            513























                0














                Here is a different solution, that also allows the replacement of a single group in multiple matches.
                It uses stacks to reverse the execution order, so the string operation can be safely executed.



                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();
                }





                share|improve this answer






























                  0














                  Here is a different solution, that also allows the replacement of a single group in multiple matches.
                  It uses stacks to reverse the execution order, so the string operation can be safely executed.



                  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();
                  }





                  share|improve this answer




























                    0












                    0








                    0







                    Here is a different solution, that also allows the replacement of a single group in multiple matches.
                    It uses stacks to reverse the execution order, so the string operation can be safely executed.



                    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();
                    }





                    share|improve this answer















                    Here is a different solution, that also allows the replacement of a single group in multiple matches.
                    It uses stacks to reverse the execution order, so the string operation can be safely executed.



                    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();
                    }






                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Jan 23 '18 at 8:48

























                    answered Jan 23 '18 at 8:20









                    Jonas_HessJonas_Hess

                    8971019




                    8971019























                        0














                        replace the password fields from the input:



                        {"_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, "**"));
                        }





                        share|improve this answer






























                          0














                          replace the password fields from the input:



                          {"_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, "**"));
                          }





                          share|improve this answer




























                            0












                            0








                            0







                            replace the password fields from the input:



                            {"_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, "**"));
                            }





                            share|improve this answer















                            replace the password fields from the input:



                            {"_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, "**"));
                            }






                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Nov 23 '18 at 7:42

























                            answered Nov 22 '18 at 9:49









                            whimmywhimmy

                            11




                            11






























                                draft saved

                                draft discarded




















































                                Thanks for contributing an answer to Stack Overflow!


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid



                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.


                                To learn more, see our tips on writing great answers.




                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function () {
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f988655%2fcan-i-replace-groups-in-java-regex%23new-answer', 'question_page');
                                }
                                );

                                Post as a guest















                                Required, but never shown





















































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown

































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown







                                Popular posts from this blog

                                "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

                                Alcedinidae

                                Origin of the phrase “under your belt”?