How to Replace Groups in Java Regex

Can I replace groups in Java regex?

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.

Replace group 1 of Java regex with out replacing the entire regex

You need to use the following pattern with capturing groups:

(\w*)lan(\w+)
^-1-^ ^-2-^

and replace with $1<--->$2

See the regex demo

The point is that we use a capturing group around the parts that we want to keep and just match what we want to discard.

Java demo:

String str = "plan plans lander planitia";
System.out.println(str.replaceAll("(\\w*)lan(\\w+)", "$1<--->$2"));
// => plan p<--->s <--->der p<--->itia

If you need to be able to replace the Group 1 and keep the rest, you may use the replace callback method emulation with Matcher#appendReplacement:

String text = "plan plans lander planitia";
String pattern = "\\w*(lan)\\w+";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(text);
StringBuffer sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, m.group(0).replaceFirst(Pattern.quote(m.group(1)), "<--->"));
}
m.appendTail(sb); // append the rest of the contents
System.out.println(sb.toString());
// output => plan p<--->s <--->der p<--->itia

See another Java demo

Here, since we process a match by match, we should only replace the Group 1 contents once with replaceFirst, and since we replace the substring as a literal, we should Pattern.quote it.

Is there a way to replace only one captured group in java matcher regex?

You can keep some groups of your regex and replace others in the occurences found in a string . if we suppose that your regex is : [\\s,\\(](%variable)[\\s,$] , then you can use the replaceAll() method of java.lang.String.
You need first to set your regex in the form of saparate groups

ex:([\\s,\\(])(%variable)([\\s,$]),
so you have

The 1st group is : [\\s,\\(]

The second group is %variable

And the third group is [\\s,$] , now you can set reference of your groups the
final value that will replace each occurence found in your regex ,for example if we want to replace the second group with the string 'myNewVal' the code will be :

String myRegex = "([\\s,\\(])(%variable)([\\s,$])";
String replacedValue = originalValue.replaceAll(myRegex,"$1myNewVal$3");

$1 and $3 refer to the first and the third group, we keep them in the replaceValue.

if you want just remove the second group you can try this :

String myRegex = "([\\s,\\(])(%variable)([\\s,$])";
String replacedValue = originalValue.replaceAll(myRegex,"$1$3");

How do you replace groups in a regular expression?

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.

Java Regex Replace with Capturing Group

How about:

if (regexMatcher.find()) {
resultString = regexMatcher.replaceAll(
String.valueOf(3 * Integer.parseInt(regexMatcher.group(1))));
}

To get the first match, use #find(). After that, you can use #group(1) to refer to this first match, and replace all matches by the first maches value multiplied by 3.

And in case you want to replace each match with that match's value multiplied by 3:

    Pattern p = Pattern.compile("(\\d{1,2})");
Matcher m = p.matcher("12 54 1 65");
StringBuffer s = new StringBuffer();
while (m.find())
m.appendReplacement(s, String.valueOf(3 * Integer.parseInt(m.group(1))));
System.out.println(s.toString());

You may want to look through Matcher's documentation, where this and a lot more stuff is covered in detail.

How to format and replace groups using RegEx (or Maybe not?) (Java)

As mentioned by codisfy it is not clear at all if you are talking about java or javascript, as you use the replaceAll method I will consider that you use java. However what I will explain hereunder is valid for most (if not all) regex engines independently about the programming language.

When you call outputString=inputString.replaceAll("REGEX","REPLACEMENT"); the method replaceAll will configure its internal regex engine, build a finite automaton (for simplicity let's omit the difference between DFA/NFA here) with the regex passed as parameter and analyse the inputString on which it is called in order to do the replacement and return the result (outputString).

When the method is called it also needs a replacement String (REPLACEMENT) that is a normal string which may contain or not back-references to some groups, in order to enable some contextual replacement (using the syntax $1, $2 or \1, \2,... depending on the language).

What is very important to understand is that the regex as well as its replacement string are both just simple strings with no special meaning outside the regex engine (the method replaceAll).

Therefore, if you reuse them in other methods (for example by passing them as parameters) they will be interpreted literally as it is the case with other normal strings.

So do not expect that $1 is replaced by name or age in your call getVar("$1"). It will be just $1 and nothing else.

Also, this being said, your method public void getVar(name){...} does not even return a string since its return type is void, as consequence, if you code in java and if you use replaceAll method of String class (which expects 2 strings as arguments) it will NOT even compile in the first place.

I will let you implement the rest of the code but if you change your replacement loop in the following way it should work:

String input="My name is %name% and I am %age% years old.";
Matcher matcher = Pattern.compile("%(\\w+)%").matcher(input);
String output=new String(input);
while (matcher.find()) {
System.out.println("------------------------------------");
System.out.println("Back reference:" + matcher.group(1));
String group=matcher.group(1);//give access to the first matching group so that it can be reused
output=output.replaceAll("%"+group+"%", getVar(group));
}

System.out.println(output);

getVar method code: (I will let you adapt it)

public static String getVar(String name){ 
if(name.equals("name"))
return "Paulo";
return "15";
}

OUTPUT:

------------------------------------
Back reference:name
------------------------------------
Back reference:age
My name is Paulo and I am 15 years old.

Java Regex Replace with Capturing Group

The definitive solution to this problem was posted by Elliott Hughes on his blog a couple years ago. Elliott keeps introducing pointless dependencies to other classes in the online version, so I'll post a stand-alone version here (the dependencies are only in the tests in the main() method).

import java.util.regex.*;

/**
* A Rewriter does a global substitution in the strings passed to its
* 'rewrite' method. It uses the pattern supplied to its constructor, and is
* like 'String.replaceAll' except for the fact that its replacement strings
* are generated by invoking a method you write, rather than from another
* string. This class is supposed to be equivalent to Ruby's 'gsub' when
* given a block. This is the nicest syntax I've managed to come up with in
* Java so far. It's not too bad, and might actually be preferable if you
* want to do the same rewriting to a number of strings in the same method
* or class. See the example 'main' for a sample of how to use this class.
*
* @author Elliott Hughes
*/
public abstract class Rewriter
{
private Pattern pattern;
private Matcher matcher;

/**
* Constructs a rewriter using the given regular expression; the syntax is
* the same as for 'Pattern.compile'.
*/
public Rewriter(String regex)
{
this.pattern = Pattern.compile(regex);
}

/**
* Returns the input subsequence captured by the given group during the
* previous match operation.
*/
public String group(int i)
{
return matcher.group(i);
}

/**
* Overridden to compute a replacement for each match. Use the method
* 'group' to access the captured groups.
*/
public abstract String replacement();

/**
* Returns the result of rewriting 'original' by invoking the method
* 'replacement' for each match of the regular expression supplied to the
* constructor.
*/
public String rewrite(CharSequence original)
{
this.matcher = pattern.matcher(original);
StringBuffer result = new StringBuffer(original.length());
while (matcher.find())
{
matcher.appendReplacement(result, "");
result.append(replacement());
}
matcher.appendTail(result);
return result.toString();
}

public static void main(String... args) throws Exception
{
String str = "12 54 1 65";

// anonymous subclass
Rewriter tripler = new Rewriter("(\\d{1,2})")
{
public String replacement()
{
int intValue = Integer.valueOf(group(1));
return String.valueOf(intValue * 3);
}
};
System.out.println(tripler.rewrite(str));

// inline subclass
System.out.println(new Rewriter("(\\d{1,2})")
{
public String replacement()
{
int intValue = Integer.valueOf(group(1));
return String.valueOf(intValue * 3);
}
}.rewrite(str));

}
}

Java replace capturing group with different value

Please consider bookmarking the Stack Overflow Regular Expressions FAQ for future reference. There's a bunch of Java-specific information in there, particularly in the "Flavor-Specific Information" section.


This works:

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

public class Replacement {
public static final void main(String[] ignored) {

String str = "fname:hello hello:world ffff:off";
Map<String, String> mapping = new HashMap<String, String>();
mapping.put("fname", "meme");
mapping.put("hello", "below");
mapping.put("ffff", "ssss");
Pattern pat = Pattern.compile("([a-zA-Z_]+):");

Matcher m = pat.matcher(str);

StringBuffer sb = new StringBuffer();
while(m.find()) {
String rplcWith = mapping.get(m.group(1));
m.appendReplacement(sb, rplcWith + ":");
}
m.appendTail(sb);

System.out.println(sb);
}
}

Output:

[C:\java_code\]java Replacement
meme:hello below:world ssss:off

How to replace content of a regex Named Capture Group in Java

I realized that I can use the start and end methods of the matcher to determine the range of characters that need to be replaced. I can then use a StringBuilder to delete the range and insert the specified replacement value. I wrote the following method to handle this situation.

public static String replaceNamedGroup(String source, Pattern pattern, String groupName, String replaceValue) {
if (source == null || pattern == null) {
return null;
}

Matcher m = pattern.matcher(source);
if (m.find()) {
int start = m.start(groupName);
int end = m.end(groupName);
StringBuilder sb = new StringBuilder(source);
sb = sb.delete(start, end);
if (replaceValue != null) {
sb = sb.insert(start, replaceValue);
}
return sb.toString();
} else {
return source;
}
}

Below is some code to show how it is used

String str = "ABC 123-123 1234 AB";
Pattern pattern = Pattern.compile("(?<department>\w+(-\w)??)\s{1,5}(?<number>\w+(-\w+)?)-(?<section>\w+)\s(?<term>\d+)\s(?<campus>\w{2})");
String output = replaceNamedGroup(str, pattern, "term", "*");
//outputs Output: ABC 123-123 * AB
System.out.println("Output: " + output);


Related Topics



Leave a reply



Submit