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.
}
java regex replace regex-group
add a comment |
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
5
Can you clarify your question, like maybe give the expected output for that input?
– Michael Myers♦
Jun 12 '09 at 20:12
add a comment |
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
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
java regex replace regex-group
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
add a comment |
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
add a comment |
7 Answers
7
active
oldest
votes
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.
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. Them.replaceFirst("number $2$1");
should bem.replaceFirst("number $3$1");
– Daniel Eisenreich
Jan 10 '18 at 9:30
add a comment |
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.
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
add a comment |
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");
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 likenumber$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
add a comment |
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.
1
The non-capturing groups are unnecessary;d(.*)d
will suffice.
– shmosel
Feb 28 '18 at 8:34
add a comment |
You can use matcher.start() and matcher.end() methods to get the group positions. So using this positions you can easily replace any text.
add a comment |
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();
}
add a comment |
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, "**"));
}
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
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. Them.replaceFirst("number $2$1");
should bem.replaceFirst("number $3$1");
– Daniel Eisenreich
Jan 10 '18 at 9:30
add a comment |
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.
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. Them.replaceFirst("number $2$1");
should bem.replaceFirst("number $3$1");
– Daniel Eisenreich
Jan 10 '18 at 9:30
add a comment |
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.
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.
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. Them.replaceFirst("number $2$1");
should bem.replaceFirst("number $3$1");
– Daniel Eisenreich
Jan 10 '18 at 9:30
add a comment |
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. Them.replaceFirst("number $2$1");
should bem.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
add a comment |
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.
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
add a comment |
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.
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
add a comment |
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.
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.
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
add a comment |
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
add a comment |
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");
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 likenumber$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
add a comment |
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");
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 likenumber$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
add a comment |
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");
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");
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 likenumber$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
add a comment |
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 likenumber$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
add a comment |
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.
1
The non-capturing groups are unnecessary;d(.*)d
will suffice.
– shmosel
Feb 28 '18 at 8:34
add a comment |
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.
1
The non-capturing groups are unnecessary;d(.*)d
will suffice.
– shmosel
Feb 28 '18 at 8:34
add a comment |
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.
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.
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
add a comment |
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
add a comment |
You can use matcher.start() and matcher.end() methods to get the group positions. So using this positions you can easily replace any text.
add a comment |
You can use matcher.start() and matcher.end() methods to get the group positions. So using this positions you can easily replace any text.
add a comment |
You can use matcher.start() and matcher.end() methods to get the group positions. So using this positions you can easily replace any text.
You can use matcher.start() and matcher.end() methods to get the group positions. So using this positions you can easily replace any text.
answered Jun 9 '10 at 14:13
ydannegydanneg
513
513
add a comment |
add a comment |
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();
}
add a comment |
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();
}
add a comment |
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();
}
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();
}
edited Jan 23 '18 at 8:48
answered Jan 23 '18 at 8:20
Jonas_HessJonas_Hess
8971019
8971019
add a comment |
add a comment |
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, "**"));
}
add a comment |
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, "**"));
}
add a comment |
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, "**"));
}
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, "**"));
}
edited Nov 23 '18 at 7:42
answered Nov 22 '18 at 9:49
whimmywhimmy
11
11
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
5
Can you clarify your question, like maybe give the expected output for that input?
– Michael Myers♦
Jun 12 '09 at 20:12