Java 全部替换,每两次替换一次
Java replace all replacing one of every two occurrences
我在一个非常简单的问题上有一个奇怪的行为。
我有一个包含很多空字符串的字符串:
"a;b;c;null;null;null;null;null;null;null;null;null;null"
我用这个方法删除的:
public String replaceAllNull(String s) {
s = s.replaceAll(";null;", ";;");
//if first item = null remove it
if(s.startsWith("null;")) {
s = s.substring(4,s.length());
}
//if last item = null remove it
if(s.endsWith(";null")) {
s = s.substring(0,s.length()-4);
}
return s;
}
在我的字符串变大并且我看到这个奇怪的输出之前它一直工作正常
"a;b;c;;null;;null;;null;;null;;"
它只会从两次中删除一次。
我想我可以理解在一个替换程序中跳过一个“;”那么我的正则表达式“;null;”无法识别第二个 null。但我不明白为什么会这样?
您可以通过拆分字符串来使用 Stream
return Stream.of(s.split(";", -1))
.map(w -> "null".equals(w) ? "" : w)
.collect(Collectors.joining(";"));
在";null;"
的一个实例被";;"
替换后,两个分号都已经被处理了,所以第二个;
不能被认为是另一个替换的开始下一次 ";null;"
事件。在另一个 "null" 被向上传递以到达下一个分号之前,无法再次匹配该模式。
您可以使用一种不尝试匹配分号的模式,但它必须检查分号是否存在。您可以使用 a positive lookbehind and a positive lookahead(在链接页面上找到 "lookahead" 和 "lookbehind")。在这里,positive 意味着它验证 lookbehind/lookahead 的模式存在,但不匹配它。
正后视的格式为 (?<=X)
,其中 X
是在主模式后面查看其是否存在的模式。此外,正向预测的格式为 (?=X)
,其中 X
是预测主模式是否存在的模式。
在这里,我们查找行首 ^
或匹配前的分号,以及行尾 $
或匹配后的分号。然后我们简单地用空字符串替换实际匹配项 "null"
。
s = s.replaceAll("(?<=^|;)null(?=$|;)", "");
一个很简单的解决方案,用这个代替上面的大代码
public String replaceAllNull(String s) {
return s.replace("null" , "");
}
Example
public static void main(String []args){
String str = "a;r;c;e;null;d;f;e;null;s;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;s;";
System.out.println(String.format("Before replacing null %s", str));
str = replaceAllNull(str);
System.out.println(String.format("After replacing null %s", str));
}
Output
Before replacing null a;r;c;e;null;d;f;e;null;s;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;s;
After replacing null a;r;c;e;;d;f;e;;s;;;;;;;;;;;;;;;;;s;
Update to avoid such words that contains null in it, an alternate is here
public static String replaceAllNull(String s) {
String[] arr = s.split(";");
for (int i = 0; i < arr.length; i++) {
if (arr[i].equalsIgnoreCase("null"))
arr[i] = "";
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < arr.length; i++) {
sb.append(arr[i]);
if (i < arr.length - 1)
sb.append(";");
}
if (s.endsWith(";"))
sb.append(";");
return sb.toString();
}
我在一个非常简单的问题上有一个奇怪的行为。
我有一个包含很多空字符串的字符串:
"a;b;c;null;null;null;null;null;null;null;null;null;null"
我用这个方法删除的:
public String replaceAllNull(String s) {
s = s.replaceAll(";null;", ";;");
//if first item = null remove it
if(s.startsWith("null;")) {
s = s.substring(4,s.length());
}
//if last item = null remove it
if(s.endsWith(";null")) {
s = s.substring(0,s.length()-4);
}
return s;
}
在我的字符串变大并且我看到这个奇怪的输出之前它一直工作正常
"a;b;c;;null;;null;;null;;null;;"
它只会从两次中删除一次。
我想我可以理解在一个替换程序中跳过一个“;”那么我的正则表达式“;null;”无法识别第二个 null。但我不明白为什么会这样?
您可以通过拆分字符串来使用 Stream
return Stream.of(s.split(";", -1))
.map(w -> "null".equals(w) ? "" : w)
.collect(Collectors.joining(";"));
在";null;"
的一个实例被";;"
替换后,两个分号都已经被处理了,所以第二个;
不能被认为是另一个替换的开始下一次 ";null;"
事件。在另一个 "null" 被向上传递以到达下一个分号之前,无法再次匹配该模式。
您可以使用一种不尝试匹配分号的模式,但它必须检查分号是否存在。您可以使用 a positive lookbehind and a positive lookahead(在链接页面上找到 "lookahead" 和 "lookbehind")。在这里,positive 意味着它验证 lookbehind/lookahead 的模式存在,但不匹配它。
正后视的格式为 (?<=X)
,其中 X
是在主模式后面查看其是否存在的模式。此外,正向预测的格式为 (?=X)
,其中 X
是预测主模式是否存在的模式。
在这里,我们查找行首 ^
或匹配前的分号,以及行尾 $
或匹配后的分号。然后我们简单地用空字符串替换实际匹配项 "null"
。
s = s.replaceAll("(?<=^|;)null(?=$|;)", "");
一个很简单的解决方案,用这个代替上面的大代码
public String replaceAllNull(String s) {
return s.replace("null" , "");
}
Example
public static void main(String []args){
String str = "a;r;c;e;null;d;f;e;null;s;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;s;";
System.out.println(String.format("Before replacing null %s", str));
str = replaceAllNull(str);
System.out.println(String.format("After replacing null %s", str));
}
Output
Before replacing null a;r;c;e;null;d;f;e;null;s;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;s;
After replacing null a;r;c;e;;d;f;e;;s;;;;;;;;;;;;;;;;;s;
Update to avoid such words that contains null in it, an alternate is here
public static String replaceAllNull(String s) {
String[] arr = s.split(";");
for (int i = 0; i < arr.length; i++) {
if (arr[i].equalsIgnoreCase("null"))
arr[i] = "";
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < arr.length; i++) {
sb.append(arr[i]);
if (i < arr.length - 1)
sb.append(";");
}
if (s.endsWith(";"))
sb.append(";");
return sb.toString();
}