41
String x = "axe pickaxe";
x = x.replace("axe", "sword");
System.out.print(x);

By this code, I am trying to replace the exact word axe with sword. However, if I run this, it prints sword picksword while I would like to print sword pickaxe only, as pickaxe is a different word from axe although it contains it. How can I fix this? Thanks

Oti Na Nai
  • 1,327
  • 4
  • 13
  • 20

6 Answers6

60

Use a regex with word boundaries \b:

String s = "axe pickaxe";
System.out.println(s.replaceAll("\\baxe\\b", "sword"));

The backslash from the boundary symbol must be escaped, hence the double-backslashes.

hiergiltdiestfu
  • 2,339
  • 2
  • 25
  • 36
  • Is there a way to avoid replacing axe if the string contains specific characters such as '!' beforehand? For example, if the string is "!axe", then axe shouldn't be replaced (which it currently does), but it should be replaced with sword if the string is "axe!". – Devin Ersoy Jun 27 '19 at 00:24
19

Include the word boundary before and after the word you want to replace.

String x = "axe pickaxe axe";
x = x.replaceAll("\\baxe\\b", "sword");
System.out.print(x);

edit output

sword pickaxe sword
SubOptimal
  • 22,518
  • 3
  • 53
  • 69
12

Some other answers suggest you to use \\b word boundaries to match an exact word. But \\bfoo\\b would match the substring foo in .foo.. If you don't want this type of behavior then you may consider using lookaround based regex.

System.out.println(string.replaceAll("(?<!\\S)axe(?!\\S)", "sword"));

Explanation:

  • (?<!\\S) Negative lookbehind which asserts that the match won't be preceded by a non-space character. i.e. the match must be preceded by start of the line boundary or a space.

  • (?!\\S) Negative lookahead which asserts that the match won't be followed by a non-space character, i.e. the match must be followed by end of the line boundary or space. We can't use (?<=^|\\s)axe(?=\\s|$) since Java doesn't support variable length lookbehind assertions.

DEMO

Maroun
  • 94,125
  • 30
  • 188
  • 241
Avinash Raj
  • 172,303
  • 28
  • 230
  • 274
  • 3
    You might attract upvoting if you explained `(?<!\\S)` – Bathsheba May 12 '15 at 07:05
  • Nah, additional explanations don't appear to attract upvotes ;-P But back on topic: your solution precludes matching the end of a sentence, doesn't it? Then again, we don't really know about the general structure of OP's data set. – hiergiltdiestfu May 12 '15 at 07:08
  • Sure. `String s = "axe. pickaxe"; System.out.println(s.replaceAll("(?<!\\S)axe(?!\\S)", "sword"));` - output: "axe. pickaxe" (Oracle JDK 1.7.0-51) – hiergiltdiestfu May 12 '15 at 07:17
  • @hiergiltdiestfu please read my solution again. I think op means the complete word as the one which don't have any character other than the original string. In your example, it has `axe.`, so it fails. I though op means the complete word as the one which don't have any char preceding or following other than space. – Avinash Raj May 12 '15 at 07:19
  • You made an assumption about the data set and some more details of the OP's intentions - that's OK. However, the OP's comments point elsewhere (see his 2nd comment on his q). Anyways, +1 for the fancy advanced lookaround stuff :) – hiergiltdiestfu May 12 '15 at 07:21
3
System.out.println("axe pickaxe".replaceAll("\\baxe\\b", "sword"));

You need to use replaceAll instead of replace - because it can work with regular expressions. Then use the meta character \b which is for word boundary. In order to use it you need to escape the \ as double \ so the reges become \\baxe\\b

Veselin Davidov
  • 7,031
  • 1
  • 15
  • 23
2

You can use \b to define the word boundary, so \baxe\b in this case.

x = x.replaceAll("\\baxe\\b");
Steve Chaloner
  • 8,162
  • 1
  • 22
  • 38
2

If you only want to replace the first occurrence, there is a method replaceFirst in String object.

String x = "axe pickaxe";
x = x.replaceFirst("axe", "sword");
System.out.print(x); //returns sword pickaxe
Alvin Magalona
  • 771
  • 3
  • 13