0

I was trying to replace concatenation symbol '+' with '||' in given multi-line script, however it seems that java regex just replaces 1 occurrence, instead of all.

String ss="A+B+C+D";
Matcher mm=Pattern.compile("(?imc)(.+)\\s*\\+\\s*(.+)").matcher(ss);

while(mm.find())
{
    System.out.println(mm.group(1));
    System.out.println(mm.group(2));
    ss=mm.replaceAll("$1 \\|\\| $2");
}

System.out.println(ss); // Output: A+B+C||D, Expected: A||B||C||D
2
  • 2
    Why not just ss.replaceAll("\\+", "||")? Commented Jun 21, 2019 at 5:54
  • @ernest_k There can be such alternate ways, but I am keen to know, why is this not working..! Commented Jun 21, 2019 at 6:05

3 Answers 3

1

The reason you only replace one element, is because you match the entire line. The regular expression you use "(?imc)(.+)\\s*\\+\\s*(.+)", matches anything (.+) until the end, then reverts, so it can match the rest \\s*\\+.... So basically your group 1 is .+ almost everything, but the last + and beyond. Therefore replaceAll can only match once, and will terminate after that one replacement. What you need is a replacement that finds + optionally wrapped in spaces:

Pattern.compile("(?imc)\\s*\\+\\s*");

This should match all you want to match, and does not match the entire line, but only your replacement character.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks @TreffnonX. That clarifies the confusion :)
1

You could just use:

ss = ss.replaceAll("\\+", "||")

as @ernest_k has pointed out. If you really want to continue using a matcher with iteration, then use Matcher#appendReplacement with a StringBuffer:

String ss = "A+B+C+D";
Matcher mm = Pattern.compile("\\+").matcher(ss);

StringBuffer sb = new StringBuffer();

while (mm.find()) {
    mm.appendReplacement(sb, "||");
}
mm.appendTail(sb);

System.out.println(sb);

2 Comments

Thanks @Tim, I am just wondering why group selectors are not working the same way ?
@Pratik First of all $1 and $2 etc. are only available in the second parameter replacement to String#replaceAll. The approach you are taking does not make much sense, because the loop means you are iterating over the input, and replaceAll is yet iterating again. Follow the pattern I gave in the second part of my answer if you want to iterate with a regex pattern.
0

I thing maybe we would just need a simple string replace:

Demo

Test

import java.util.regex.Matcher;
import java.util.regex.Pattern;

final String regex = "\\+";
final String string = "A+B+C+D";
final String subst = "||";

final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
final Matcher matcher = pattern.matcher(string);
final String result = matcher.replaceAll(subst);

System.out.println(result);

This link on the right panel explains your original expression. The first capturing group does match between one and unlimited times, as many times as possible, thus it would not work here. If we would have changed them to (.+?), it would have partially worked, yet still unnecessary.

1 Comment

Thanks @Emma, I am just wondering why group selectors are not working the same way ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.