说我有一个文件,其中包含一些文本。有“substr1”,“substr2”,“substr3”等子字符串。我需要用其他文本替换所有这些子字符串,如“repl1”,“repl2”,“repl3”。在Python中,我将创建一个这样的解释:立即替换多个子字符串
{
"substr1": "repl1",
"substr2": "repl2",
"substr3": "repl3"
}
和创建模式加入与键“|”,然后用re.sub
功能替代。 在Java中是否有类似的简单方法?
说我有一个文件,其中包含一些文本。有“substr1”,“substr2”,“substr3”等子字符串。我需要用其他文本替换所有这些子字符串,如“repl1”,“repl2”,“repl3”。在Python中,我将创建一个这样的解释:立即替换多个子字符串
{
"substr1": "repl1",
"substr2": "repl2",
"substr3": "repl3"
}
和创建模式加入与键“|”,然后用re.sub
功能替代。 在Java中是否有类似的简单方法?
这是你的Python-建议如何转换为Java:
Map<String, String> replacements = new HashMap<String, String>() {{
put("substr1", "repl1");
put("substr2", "repl2");
put("substr3", "repl3");
}};
String input = "lorem substr1 ipsum substr2 dolor substr3 amet";
// create the pattern joining the keys with '|'
String regexp = "substr1|substr2|substr3";
StringBuffer sb = new StringBuffer();
Pattern p = Pattern.compile(regexp);
Matcher m = p.matcher(input);
while (m.find())
m.appendReplacement(sb, replacements.get(m.group()));
m.appendTail(sb);
System.out.println(sb.toString()); // lorem repl1 ipsum repl2 dolor repl3 amet
这种方法做了simultanious(即 “一次”)替换。即,如果你碰巧有
"a" -> "b"
"b" -> "c"
那么这种做法将给"a b" -> "b c"
,而不是答案建议你应该链多次打电话给replace
或replaceAll
这将使"c c"
。
(如果推广这种方法以编程方式创建的正则表达式,请确保您Pattern.quote
每个单独的搜索词和Matcher.quoteReplacement
每个替换词。)
return yourString.replaceAll("substr1","relp1").
replaceAll("substr2","relp2").
replaceAll("substr3","relp3")
-1。这不是全部,并且不必要地使用正则表达式方法(replaceAll)而不是普通的String方法(replace)。 – Boann
首先,问题的演示:
String s = "I have three cats and two dogs.";
s = s.replace("cats", "dogs")
.replace("dogs", "budgies");
System.out.println(s);
这是为了取代猫=>狗和狗=> budgies,但顺序替换操作的结果前一个r所以不幸的输出是:
我有三budgies和两budgies。
这是我的同步替换方法的实现。这很容易使用String.regionMatches
写:
public static String simultaneousReplace(String subject, String... pairs) {
if (pairs.length % 2 != 0) throw new IllegalArgumentException(
"Strings to find and replace are not paired.");
StringBuilder sb = new StringBuilder();
int numPairs = pairs.length/2;
outer:
for (int i = 0; i < subject.length(); i++) {
for (int j = 0; j < numPairs; j++) {
String find = pairs[j * 2];
if (subject.regionMatches(i, find, 0, find.length())) {
sb.append(pairs[j * 2 + 1]);
i += find.length() - 1;
continue outer;
}
}
sb.append(subject.charAt(i));
}
return sb.toString();
}
测试:
String s = "I have three cats and two dogs.";
s = simultaneousReplace(s,
"cats", "dogs",
"dogs", "budgies");
System.out.println(s);
输出:
我有三条狗和两个虎皮鹦鹉。
此外,它在进行同步替换时有时很有用,以确保查找最长匹配。 (例如,PHP的strtr
函数执行此操作。)这是我的实现:
public static String simultaneousReplaceLongest(String subject, String... pairs) {
if (pairs.length % 2 != 0) throw new IllegalArgumentException(
"Strings to find and replace are not paired.");
StringBuilder sb = new StringBuilder();
int numPairs = pairs.length/2;
for (int i = 0; i < subject.length(); i++) {
int longestMatchIndex = -1;
int longestMatchLength = -1;
for (int j = 0; j < numPairs; j++) {
String find = pairs[j * 2];
if (subject.regionMatches(i, find, 0, find.length())) {
if (find.length() > longestMatchLength) {
longestMatchIndex = j;
longestMatchLength = find.length();
}
}
}
if (longestMatchIndex >= 0) {
sb.append(pairs[longestMatchIndex * 2 + 1]);
i += longestMatchLength - 1;
} else {
sb.append(subject.charAt(i));
}
}
return sb.toString();
}
为什么你需要这个?举例如下:
String truth = "Java is to JavaScript";
truth += " as " + simultaneousReplaceLongest(truth,
"Java", "Ham",
"JavaScript", "Hamster");
System.out.println(truth);
输出:
Java是对JavaScript作为火腿是仓鼠
如果我们使用的simultaneousReplace
代替simultaneousReplaceLongest
,输出将不得不 “HamScript”而不是“仓鼠”:)
请注意,上述方法是区分大小写的。如果您需要不区分大小写的版本,则可以轻松修改上述内容,因为String.regionMatches
可以使用ignoreCase
参数。
相关主题 - http://stackoverflow.com/questions/2049528/java-best-way-for-string-find-and-replace – adatapost