1

I want to replace the replaceEntry (@length) with newEntry but there are some replaceEntrys with additional content I don't want to be replaced (eg @length.article). If I just look for the pattern without grouping it, it replaces the replaceEntry and the following char but I just want to replace the entry. Is the Regex wrong or something else?

private String replace(String code){
String code = "@length Lorem ipsum dolor sit amet, consetetur sadipscing elitr, @length.article sed diam 
               nonumy eirmod tempor invidunt ut labore et dolore magna @length.media aliquyam erat, sed 
               diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd 
               gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem @length_name 
               ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt 
               ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et 
               justo duo dolores et @length ea rebum. Stet clita kasd gubergren, no sea takimata sanctus 
               est Lorem ipsum dolor sit amet. @length";

String replaceEntry = "@length";
String newEntry = "@column";

Pattern pattern = Pattern.compile("(" + replaceEntry + ")([^\\w-\\.])");
        Matcher matcher = pattern.matcher(code);

        String newCode = code.replaceAll(matcher.group(1), newEntry);

        return newCode;
}
Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Nick B.
  • 13
  • 2
  • `Pattern pattern = Pattern.compile("(" + replaceEntry + ")(?![\\w.-])");`? BTW, you need no parentheses round the search term, use `Pattern.compile(replaceEntry"(?![\\w.-])")` and then get it via `matcher.group()` – Wiktor Stribiżew Feb 25 '20 at 09:36
  • Just a good practice is to quote the variable you insert inside the pattern: `Pattern pattern = Pattern.compile("(" + Pattern.quote(replaceEntry) + ")(?![\\w.-])");` – Alex Sveshnikov Feb 25 '20 at 09:42
  • @Alex That might not be a case here, since all those `replaceEntries` seem to be identifiers and can't contain special regex metacharacters. – Wiktor Stribiżew Feb 25 '20 at 09:43
  • @WiktorStribiżew true, just a good practice, like prepare statement in sql query. – Alex Sveshnikov Feb 25 '20 at 09:45

2 Answers2

0

You should use a lookahead to capture a group without the next chars but still be able to read them. Example

@length(?!\.)

This matches @length, then make sure a dot cannot be read after (but does not read the dot)

@length and @length are @length.details matches: at index 0 [@length], at index 12 [@length]

David Amar
  • 247
  • 1
  • 5
0

You may fix your pattern by replacing the ([^\\w-\\.]) capturing group with "(?![\\w.-])" negative lookahead pattern, a non-consuming pattern that reads, checks the string but does not add the matched substring to the match value.

You might use

Pattern.compile(replaceEntry + "(?![\\w.-])")

See the regex demo.

Or, in case the replaceEntry list may contain an item with special regex metacharacters, use Pattern.quote() to escape them and be treated as literal chars:

Pattern.compile(Pattern.quote(replaceEntry) + "(?![\\w.-])")

If the replaceEntry always ends with whitespace or end of string, you may simply rely on a whitespace boundary:

Pattern.compile(Pattern.quote(replaceEntry) + "(?!\\S)")

See the regex demo.

The (?!\S) negative lookahead requires a whitespace or end of string immediately to the right of the current location.

When you replace, do not forget to use Group 0, the whole match:

String newCode = code.replaceAll(matcher.group(), newEntry);
                                              ^^

If there are no additional code lines, you may reduce the three lines

Pattern pattern = Pattern.compile("(" + replaceEntry + ")([^\\w-\\.])");
Matcher matcher = pattern.matcher(code);
String newCode = code.replaceAll(matcher.group(1), newEntry);

to

String newCode = code.replaceAll(Pattern.quote(replaceEntry) + "(?![\\w.-])", newEntry);
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • 1
    Thanks a lot for the quick answers. It worked well. I'm new in coding. May u can tell me why I always got an IllegalStateException with my posted code? :) – Nick B. Feb 25 '20 at 10:04
  • @NickB. You did not call `matcher.find()`, you only initialized the matcher and then asked it to provide you the Group 1 value, but matcher did not know what it was. – Wiktor Stribiżew Feb 25 '20 at 10:08