Reputation: 463
consider the scenario below i have an input string
"input [yes] [yes] [yes] [mk:[yes] [yes] [yes]] [yes] [iif:[yes] [yes] [yes]]"
my desired out string after replace all is all [yes]
will be replaced with Yes
however if it is nested within a secondary or n-backets such patterns should be ignored, the assumption here is that all opening brackets will be properly closed, here is the desired output string
"input Yes Yes Yes [mk:[yes] [yes] [yes]] Yes [iif:[yes] [yes] [yes]]"
here is my question in a nutshell, can regex understand 'nested' patterns? or is recursion an absolute necessity in doing accomplishing this and regex is simply not sufficient enough
if detecting infinitely nested regex cannot be done, how about nested to the second degree only like my examples
Upvotes: 2
Views: 511
Reputation: 5395
Try with:
\[[^\[\]]+\[.+?][^\[\]]*\]|\[([a-z])[^\[\]]+\]
With this you will match the whole nested brackets, or not-nested bracket. Then replace content only if Matcher
will find group(1)
(not nested bracket), like in:
public class Test {
public static void main(String[] args){
String[] strings = {"input [yes] [yes] [yes] [mk:[yes] [yes] [yes]] [yes] [iif:[yes] [yes] [yes]]",
"input [yes] [yes] [yes[yes] [yes] [yes] [mk:[yes] [yes] [yes]] [yes] [mk:[yes] [yes] [yes]] [yes] [iif:[yes] [yes] [yes]]",
"input [yes] [yes] [yes[yes] [yes] [yes] [mk:[yes] [yes] [yes]] [mk:[yes] [yes] [yes]] [yes] [iif:[yes] [yes] [yes]]"};
Pattern pattern = Pattern.compile("\\[[^\\[\\]]+\\[.+?][^\\[\\]]*\\]|\\[([a-z])[^\\[\\]]+\\]");
for(String string : strings) {
Matcher matcher = pattern.matcher(string);
while (true) {
if (matcher.find()) {
if (matcher.group(1) != null) {
string = string.substring(0, matcher.start(1)) + string.substring(matcher.start(1), matcher.end(1)).toUpperCase() + string.substring(matcher.end(1));
matcher.reset(string);
}
} else {
break;
}
}
System.out.println(string);
}
}
}
which gives output:
input [Yes] [Yes] [Yes] [mk:[yes] [yes] [yes]] [Yes] [iif:[yes] [yes] [yes]]
input [Yes] [Yes] [yes[yes] [yes] [yes] [mk:[yes] [yes] [yes]] [Yes] [mk:[yes] [yes] [yes]] [Yes] [iif:[yes] [yes] [yes]]
input [Yes] [Yes] [yes[yes] [yes] [yes] [mk:[yes] [yes] [yes]] [mk:[yes] [yes] [yes]] [Yes] [iif:[yes] [yes] [yes]]
Upvotes: 1
Reputation: 3036
EDIT 1
As this cannot be done with regex as pointed out by vks, I wrote a simple program that'll do the same for you in Java:
public class Main {
public static String nestedReplace(String s) {
int nested =0,i=0;
StringBuilder o = new StringBuilder();
while(i<s.length())
{
if(nested==0 && s.regionMatches(i,"[yes]",0,4))
{
o.append("Yes");
i += 5;
continue;
}
else if(s.charAt(i) == '[')
nested++;
else if(s.charAt(i) == ']')
nested--;
o.append(s.charAt(i));
i++;
}
return new String(o);
}
public static void main(String[] args) {
System.out.println(nestedReplace("input [yes] [yes] [yes] [mk:[yes] [yes] [yes]] [yes] [iif:[yes] [yes] [yes]]"));
}
}
Output:
input Yes Yes Yes [mk:[yes] [yes] [yes]] Yes [iif:[yes] [yes] [yes]]
Upvotes: 2