5

I want to find all patterns in a string that match the regex: no="(\d+)" then replace the digits in the group with something else.

In the method below I can find and replace the entire match, but that is not what I want. Is there a way to replace just a portion in that match?

private String replaceStringFromPatternSearch(String stringToSearch, String patternString, String replacementString) {
    String replacedString = null;
    Pattern stringPattern = Pattern.compile(patternString);

    Matcher stringMatcher = stringPattern.matcher(stringToSearch);
    replacedString = stringMatcher.replaceAll(replacementString);
    if (replacedString != null) {
        return replacedString;
    } else {
        return stringToSearch;
    }
}
zx81
  • 41,100
  • 9
  • 89
  • 105
Phillip Gibb
  • 523
  • 1
  • 6
  • 19
  • 3
    can you give sample input/output – Scary Wombat Jul 31 '14 at 07:02
  • See accepted solution here: http://stackoverflow.com/a/25047477/1382300 – inigoD Jul 31 '14 at 07:02
  • Hi philip, your regex will replace any long number. What exactly you want, please give an example – aelor Jul 31 '14 at 07:02
  • I have given example data in the answer that I posted myself. The way I am implementing this allows me to use the same regex to search for a string in one string and then replace it in another. String1 : String2 : So I can pull out 1111111111 from String1 and replace 07040365089 with it in String2 – Phillip Gibb Jul 31 '14 at 10:10

3 Answers3

13

No Callbacks / Lambdas in Java Replace, But We Have Other Options

Option 1: Use Capture Buffers in Replacement Function

In replaceAll, you can build your replacement from components such as captured text and strings you want to insert at that time. Here is an example:

String replaced = yourString.replaceAll("no=\"(\\d+)\"", 
                                         "Something $1 Something else");

In the replacement, $1 are the captured digits. You don't have to use them, but as you can see you can build a replacement string around them.

Option 2 (Replacement Lambda/Callback/Delegate Equivalent): Build it One Match At a Time

In Java, to build even more sophisticated replacement, we don't have replacement lambdas, but we can do this:

StringBuffer resultString = new StringBuffer();
Pattern regex = Pattern.compile("no=\"(\\d+)\"");
Matcher regexMatcher = regex.matcher(subjectString);
while (regexMatcher.find()) {
        // You can vary the replacement text for each match on-the-fly
        // String computed_replacement = .... Something wild!
        regexMatcher.appendReplacement(resultString, computed_replacement );
    } 
regexMatcher.appendTail(resultString);
zx81
  • 41,100
  • 9
  • 89
  • 105
  • thanks, this approach put me on the right track for a more effective solution than substringing with the start and end of the group – Phillip Gibb Jul 31 '14 at 10:14
1

You could use lookarounds, so that the matches will only be the digits:

(?<=no=")\d+(?=")

Regular expression visualization

Debuggex Demo

sp00m
  • 47,968
  • 31
  • 142
  • 252
0

both of these methods solve my problem:

Example Data: <detail type="07" time="100611" no="07040365089" detail">

with the idea that I want to replace 07040365089 with something else. no="\d" occurs multiple times in the actual data. There are other replacements that are required for different patterns.

private String replaceStringFromPatternSearch2(String stringToSearch, String patternString, String replacementString) {
    String replacedString = "";
    Pattern stringPattern = Pattern.compile(patternString);
    int startSearch = 0;
    Matcher stringMatcher = stringPattern.matcher(stringToSearch);
    while (stringMatcher.find(startSearch)) {
        int start = stringMatcher.start(1);
        int end = stringMatcher.end(1);
        replacedString += stringToSearch.substring(startSearch, start) + replacementString + stringToSearch.substring(end);
        startSearch = end + 1;
    }
    if (!replacedString.isEmpty()) {
        return replacedString;
    } else {
        return stringToSearch;
    }
}

private String replaceStringFromPatternSearch(String stringToSearch, String patternString, String replacementString) {
    String replacedString = "";
    Pattern stringPattern = Pattern.compile(patternString);
    int startSearch = 0;
    Matcher stringMatcher = stringPattern.matcher(stringToSearch);
    StringBuffer sb = new StringBuffer();
    while (stringMatcher.find()) {
        String wholeGroup = stringMatcher.group(0);
        replacedString = wholeGroup.replace(stringMatcher.group(1), replacementString);
        stringMatcher.appendReplacement(sb, replacedString);
    }
    stringMatcher.appendTail(sb);
    if (sb.length() > 0) {
        return sb.toString();
    } else {
        return stringToSearch;
    }
}
Phillip Gibb
  • 523
  • 1
  • 6
  • 19