Replacing one static String
with another can be done in various ways:
public final class ReplaceSubstring { /** * Simplest in Java 1.5, using the replace method, which * takes CharSequence objects. */ public static String replace15( String input, String oldPattern, String newPattern ){ return input.replace(oldPattern, newPattern); } /** * Not quite as simple in Java 1.4. The replaceAll method works, * but requires more care, since it uses regular expressions, which * may contain special characters. */ public static String replace14( String input, String oldPattern, String newPattern ){ /* * The replaceAll method is a bit dangerous to use. * The oldPattern is converted into a regular expression. * Thus, if oldPattern may contain characters which have * special meaning to regular expressions, then they must * be 'escaped' before being passed to replaceAll. It is * easy to forget to do this. * * In addition, aNewPattern treats '$' as special characters * as well: they refer to 'back references'. */ return input.replaceAll(oldPattern, newPattern); /* Here is an alternative implementation using Pattern and Matcher, which is preferred when the same pattern is used repeatedly final Pattern pattern = Pattern.compile(oldPattern); final Matcher matcher = pattern.matcher(iInput); return matcher.replaceAll(newPattern); */ } /** * In really old versions of Java (before 1.4)the following technique may be used. * * @param input is the original String which may contain substring oldPattern * @param oldPattern is the non-empty substring which is to be replaced * @param newPattern is the replacement for oldPattern */ public static String replaceOld( final String input, final String oldPattern, final String newPattern ){ if ( oldPattern.equals("") ) { throw new IllegalArgumentException("Old pattern must have content."); } final StringBuffer result = new StringBuffer(); //startIdx and idxOld delimit various chunks of aInput; these //chunks always end where aOldPattern begins int startIdx = 0; int idxOld = 0; while ((idxOld = input.indexOf(oldPattern, startIdx)) >= 0) { //grab a part of aInput which does not include aOldPattern result.append( input.substring(startIdx, idxOld) ); //add aNewPattern to take place of aOldPattern result.append( newPattern ); //reset the startIdx to just after the current match, to see //if there are any further matches startIdx = idxOld + oldPattern.length(); } //the final chunk will go to the end of aInput result.append( input.substring(startIdx) ); return result.toString(); } /** Example: update an ip address appearing in a link. */ public static void main (String... arguments) { String OLD_IP = "45.23.102.12"; //escape the '.', a special character in regular expressions String OLD_IP_REGEX = "45\\.23\\.102\\.12"; String NEW_IP = "99.104.106.95"; String LINK = "http://45.23.102.12:8080/index.html"; log("Old link : " + LINK); String newLink = replace15(LINK, OLD_IP, NEW_IP); log("New link with Java 1.5 replace: " + newLink); newLink = replace14(LINK, OLD_IP_REGEX, NEW_IP); log("New link with Java 1.4 replaceAll: " + newLink); newLink = replaceOld(LINK, OLD_IP, NEW_IP); log("New link with oldest style: " + newLink); } private static void log(String message){ System.out.println(message); } }
Old link : http://45.23.102.12:8080/index.html New link with Java 1.5 replace: http://99.104.106.95:8080/index.html New link with Java 1.4 replaceAll: http://99.104.106.95:8080/index.html New link with oldest style: http://99.104.106.95:8080/index.html
Dynamic Replacement
If the replacement string is not fixed, and needs to be created dynamically,
then another approach is required. In the following example, strings of
the form "href='TopicAction.do?Id=182'
" are replaced with a corresponding
string "href=#182
".
The number 182
is taken only as an example. It is in fact extracted
dynamically, and referenced in the replacement string using the back reference
"$1
", where 1
is the index of the matching group for
these digits.
import java.util.regex.*; public final class ReplaceSubstringDynamically { public static void main (String... arguments) { String htmlText = "<a href=\"Topic27.cjp\">xyz</a> blah <a href=Topic8.cjp>abc</a>"; ReplaceSubstringDynamically replace = new ReplaceSubstringDynamically(); log("Old HTML text : " + htmlText); log("New HTML text : " + replace.replaceLinks(htmlText)); } /** * Replace the document links in a snippet of HTML with corresponding * fragment links, which start with the # sign, and refer to labeled * locations within a single document. */ String replaceLinks(String htmlTextWithLinks){ Pattern pattern = Pattern.compile(LINK); Matcher matcher = pattern.matcher(htmlTextWithLinks); return matcher.replaceAll(FRAGMENT); } /** * The single matching group of this regex are the digits ((?:\\d){1,3}), * which correspond to group 1. */ private static String LINK = "href=(?:\"|\')?Topic((?:\\d){1,3})\\.cjp(?:\"|\')?"; /** * The "$1" refers to matching group 1 of fLINK (the digits). */ private static String FRAGMENT = "href=#$1"; private static void log(String msg) { System.out.println(msg); } }
Old HTML text : <a href='TopicAction.do?Id=27'>xyz</a> blah <a href='TopicAction.do?Id=8'>abc</a>
New HTML text : <a href=#27>xyz</a> blah <a href=#8>abc</a>
Here's a second example, where the replacement string is computed without
using back references.
import java.util.regex.*; public final class ReplaceSubstringAppendReplacement { public static void main (String... args) { String text = "Apples and oranges are better for all."; ReplaceSubstringAppendReplacement repl = new ReplaceSubstringAppendReplacement(); System.out.println("Old text : " + text); System.out.println("New text : " + repl.getEditedText(text)); } /** * Replace all words starting with the letter 'a' or 'A' with * their uppercase forms. */ String getEditedText(String text){ StringBuffer result = new StringBuffer(); Matcher matcher = INITIAL_A.matcher(text); while (matcher.find()) { matcher.appendReplacement(result, getReplacement(matcher)); } matcher.appendTail(result); return result.toString(); } private static final Pattern INITIAL_A = Pattern.compile( "(?:\\s|^)a(?:\\w)*", Pattern.CASE_INSENSITIVE ); private String getReplacement(Matcher matcher){ return matcher.group(0).toUpperCase(); } private static void log(String msg) { System.out.println(msg); } }
Old text : Apples and oranges are better for all.
New text : APPLES AND oranges ARE better for ALL.
Warning
The methods:
String.replaceAll(String, String)
String.replaceFirst(String, String)
Matcher.appendReplacement(StringBuffer, String)
'$'
and '\\'
in the replacement text as special characters.
If the replacement text can contain arbitrary text, then these characters will usually be escaped using
Matcher.quoteReplacement(String)
.