Replace all occurrences of group
Asked Answered
C

3

5

I want to replace all the occurrences of a group in a string.

String test = "###,##.##0.0########";
System.out.println(test);
test = test.replaceAll("\\.0(#)", "0");
System.out.println(test);

The result I am trying to obtain is ###,##.##0.000000000 Basically, I want to replace all # symbols that are trailing the .0. I've found this about dynamic replacement but I can't really make it work.

The optimal solution will not take into account the number of hashes to be replaced (if that clears any confusion).

Cloudlet answered 26/5, 2015 at 9:50 Comment(5)
So you want to replace all the # following .0 to 0?Bekah
@Bekah . Yes, sorry about the confusion, I've added the explanation.Cloudlet
How many hash symbols to replace with 0 can there be in an input string? Unlimited, or say, a hundred?Headstone
Well right now it's about 4 or less, but I would prefer if it's a solution about unlimited hash symbols.Cloudlet
-(int)PI/3: NOT ENOUGH REGEX!Forborne
S
5

You can use a simple regex to achieve your task.

#(?=#*+$)

(?=#*+$) = A positive look-ahead that checks for any # that is preceded by 0 or more # symbols before the end of string $. Edit: I am now using a possessive quantifier *+ to avoid any performance issues.

See demo

IDEONE:

String test = "###,##.##0.0###########################################";
test = test.replaceAll("#(?=#*+$)", "0");
System.out.println(test);
Scotsman answered 26/5, 2015 at 10:6 Comment(5)
Glad to help. I also think that you can even further optimize this by using possessive quantifier: #(?=#*+$). I edited the answer.Headstone
Performance is not an issue here since we are talking about small strings, but still, it's great to know the difference. Is it possible to explain step by step the regex operation? Although the answers solve my problem, it would be great if the material existed (teach someone to fish...)Cloudlet
I had an answer with a look-behind the earliest, but you said you consider an unlimited number of #. So, I had to think of a different approach. I also provided some links for you to "learn to fish" :)Headstone
Yeap, you are right, I did ask for that. So basically this ?=# (the positive look-ahead) causes to stop when it encounters anything other than a # right? Thank you for the material too.Cloudlet
(?=#) is checking if there is a # symbol right after. (?=#*$) will check if there are 0 or more # symbols before the end of string but will store backtracking information after each match. #*+ will not store that backtracking information which can greatly enhance performance and avoid catastrophic backtracking.Headstone
T
7
#(?!.*\\.0)

You can try this.Replace by 0.See demo.

https://regex101.com/r/yW3oJ9/12

Tidbit answered 26/5, 2015 at 10:1 Comment(2)
If I understand correctly, it goes like this : Replace every # but discard everything the precedes .0 . Could you explain the ?! ?Cloudlet
@alkis ?! is negative lookahead.It will replace every # which does not have .0 ahead of it.Tidbit
S
5

You can use a simple regex to achieve your task.

#(?=#*+$)

(?=#*+$) = A positive look-ahead that checks for any # that is preceded by 0 or more # symbols before the end of string $. Edit: I am now using a possessive quantifier *+ to avoid any performance issues.

See demo

IDEONE:

String test = "###,##.##0.0###########################################";
test = test.replaceAll("#(?=#*+$)", "0");
System.out.println(test);
Scotsman answered 26/5, 2015 at 10:6 Comment(5)
Glad to help. I also think that you can even further optimize this by using possessive quantifier: #(?=#*+$). I edited the answer.Headstone
Performance is not an issue here since we are talking about small strings, but still, it's great to know the difference. Is it possible to explain step by step the regex operation? Although the answers solve my problem, it would be great if the material existed (teach someone to fish...)Cloudlet
I had an answer with a look-behind the earliest, but you said you consider an unlimited number of #. So, I had to think of a different approach. I also provided some links for you to "learn to fish" :)Headstone
Yeap, you are right, I did ask for that. So basically this ?=# (the positive look-ahead) causes to stop when it encounters anything other than a # right? Thank you for the material too.Cloudlet
(?=#) is checking if there is a # symbol right after. (?=#*$) will check if there are 0 or more # symbols before the end of string but will store backtracking information after each match. #*+ will not store that backtracking information which can greatly enhance performance and avoid catastrophic backtracking.Headstone
T
2

You can split your text on "0.0" and replace just for the second part:

String[] splited = "###,##.##0.0########".split("0.0");
String finalString = splited[0] + "0.0" + splited[1].replaceAll("#","0");
Trixy answered 26/5, 2015 at 10:1 Comment(1)
I prefer a regex solution. Sorry if I was not clear enough. This is valid though, so upvoted.Cloudlet

© 2022 - 2024 — McMap. All rights reserved.