Java:String.replaceAll(正则表达式,替换);
Java: String.replaceAll(regex, replacement);
我有一串以逗号分隔的用户 ID,我想从字符串中 eliminate/remove 特定的用户 ID。
我已经关注字符串的可能性并期待结果
int elimiateUserId = 11;
String css1 = "11,22,33,44,55";
String css2 = "22,33,11,44,55";
String css3 = "22,33,44,55,11";
// The expected result in all cases, after replacement, should be:
// "22,33,44,55"
我尝试了以下方法:
String result = css#.replaceAll("," + elimiateUserId, ""); // # = 1 or 2 or 3
result = css#.replaceAll(elimiateUserId + "," , "");
这个逻辑在 css3
的情况下失败。请建议我解决此问题的正确方法。
注意:我正在使用 Java 7
我查看了以下帖子,但找不到任何解决方案:
- Java String.replaceAll regex
- java String.replaceAll regex question
- Java 1.3 String.replaceAll() , replacement
尝试将(^(11)(?:,))|((?<=,)(11)(?:,))|(,11$)
表达为replaceAll
:
final String regexp = MessageFormat.format("(^({0})(?:,))|((?<=,)({0})(?:,))|(,{0}$)", elimiateUserId)
String result = css#.replaceAll(regexp, "") //for all cases.
这是一个例子:
https://regex101.com/r/LwJgRu/3
您可以在 Java 8:
中使用 Stream API
int elimiateUserId = 11;
String css1 = "11,22,33,44,55";
String css1Result = Stream.of(css1.split(","))
.filter(value -> !String.valueOf(elimiateUserId).equals(value))
.collect(Collectors.joining(","));
// css1Result = 22,33,44,55
这应该有效
replaceAll("(11,|,11)", "")
至少当你能保证没有311的时候,或者,113左右
如果你想使用正则表达式,你可以使用(记得正确转义为 java 字符串文字)
,\b11\b|\b11\b,
这将确保 11 不会由于单词边界而被匹配为另一个数字的一部分,并且只会匹配和删除一个逗号(如果存在两个逗号)。
您可以一次使用两个替换,例如:
int elimiateUserId = 11;
String result = css#.replace("," + elimiateUserId , "").replace(elimiateUserId + ",", "");
如果您的字符串类似于 ,11
,则第一个替换会将其替换为空字符串
如果您的字符串类似于 11,
,则第二个替换会将其替换为空
结果
11,22,33,44,55 -> 22,33,44,55
22,33,11,44,55 -> 22,33,44,55
22,33,44,55,11 -> 22,33,44,55
你可以像这样构建一个正则表达式
^11,|,11\b
将匹配字符串开头的 11,
(^11,
) 或 (|
) ,11
后面没有任何其他单词 char (,11\b
).
参见regex demo。
int elimiate_user_id = 11;
String pattern = "^" + elimiate_user_id + ",|," + elimiate_user_id + "\b";
System.out.println("11,22,33,44,55,111".replaceAll(pattern, "")); // => 22,33,44,55,111
System.out.println("22,33,11,44,55,111".replaceAll(pattern, "")); // => 22,33,44,55,111
System.out.println("22,33,44,55,111,11".replaceAll(pattern, "")); // => 22,33,44,55,111
我认为维护一个白名单比较安全,然后将其作为参考进行进一步的更改。
List<String> whitelist = Arrays.asList("22", "33", "44", "55");
String s = "22,33,44,55,11";
String[] sArr = s.split(",");
StringBuilder ids = new StringBuilder();
for (String id : sArr) {
if (whitelist.contains(id)) {
ids.append(id).append(", ");
}
}
String r = ids.substring(0, ids.length() - 2);
System.out.println(r);
试试这个:
String result = css#.replaceAll("," + elimiateUserId, "")
.replaceAll(elimiateUserId + "," , "");
String result = css#.replaceAll("," + eliminate_user_id + "\b|\b" + eliminate_user_id + ",", '');
这里的正则表达式是:
, A leading comma.
eliminate_user_id I assumed the missing 'n' here was a typo.
\b Word boundary: word/number characters end here.
| OR
\b Word boundary: word/number characters begin here.
eliminate_user_id again.
, A trailing comma.
单词边界标记,匹配 "word" 的开头或结尾,是这里的魔法。这意味着 11 将匹配这些字符串:
11,22,33,44,55
22,33,11,44,55
22,33,44,55,11
但不是这些字符串:
111,112,113,114
411,311,211,111
不过,还有一种更简洁的方法:
String result = css#.replaceAll("(,?)\b" + eliminate_user_id + "\b(?(1)|,)", "");
这里的正则表达式是:
( A capturing group - what's in here, is in group 1.
,? An optional leading comma.
) End the capturing group.
\b Word boundary: word/number characters begin here.
eliminate_user_id I assumed the missing 'n' here was a typo.
\b Word boundary: word/number characters end here.
(?(1) If there's something in group 1, then require...
| ...nothing, but if there was nothing, then require...
, A trailing comma.
) end the if.
此处的 "if" 部分有点不寻常 - 您可以在此处找到有关正则表达式条件的更多信息:http://www.regular-expressions.info/conditional.html
我不确定 Java 是否支持正则表达式条件。这里的一些帖子 (Conditional Regular Expression in Java?) 表明它没有 :(
旁注:为了性能,如果列表很长并且要执行的删除操作非常多,最明显的选择是 运行 上面一行中的每个要删除的数字:
String css = "11,22,33,44,55,66,77,88,99,1010,1111,1212,...";
Array<String> removals = ["11", "33", "55", "77", "99", "1212"];
for (i=0; i<removals.length; i++) {
css = css.replaceAll("," + removals[i] + "\b|\b" + eliminate_user_id + ",", "");
}
(代码未测试:此处无法访问 Java 编译器)
这将足够快(从 n 个 ID 的字符串中删除 m 的最坏情况大约为 O(m*n)),但我们也许可以做得更好。
一种是将正则表达式构建为 \b(11,42,18,13,123,...etc)\b
- 即让正则表达式同时搜索所有要删除的 ID。从理论上讲,这种缩放比例更差一些,在每种情况下都以 O(m*n) 缩放,而不是最坏的情况,但实际上应该快得多。
String css = "11,22,33,44,55,66,77,88,99,1010,1111,1212,...";
Array<String> removals = ["11", "33", "55", "77", "99", "1212"];
String removalsStr = String.join("|", removals);
css = css.replaceAll("," + removalsStr + "\b|\b" + removalsStr + ",", "");
但另一种方法可能是构建长字符串中 ID 的哈希表,然后从哈希表中删除所有 ID,然后将剩余的哈希表键连接回字符串。由于哈希表查找对于稀疏哈希表来说实际上是 O(1),这使得这个规模与 O(n) 成正比。不过,这里的权衡是该哈希表的额外内存。
(如果没有 java 编译器,我不认为我可以做这个版本。我不会推荐这种方法,除非你有一个 VAST(数千)ID 列表要删除,无论如何,因为这将是更丑陋和更复杂的代码。
如果您需要使用 Regex 的解决方案,那么下面的方法非常有效。
int elimiate_user_id = 11;
String css1 = "11,22,33,44,55";
String css2 = "22,33,11,44,55";
String css3 = "22,33,44,55,11";
String resultCss=css1.replaceAll(elimiate_user_id+"[,]*", "").replaceAll(",$", "");
我处理您想要的所有类型的输入。
我有一串以逗号分隔的用户 ID,我想从字符串中 eliminate/remove 特定的用户 ID。
我已经关注字符串的可能性并期待结果
int elimiateUserId = 11;
String css1 = "11,22,33,44,55";
String css2 = "22,33,11,44,55";
String css3 = "22,33,44,55,11";
// The expected result in all cases, after replacement, should be:
// "22,33,44,55"
我尝试了以下方法:
String result = css#.replaceAll("," + elimiateUserId, ""); // # = 1 or 2 or 3
result = css#.replaceAll(elimiateUserId + "," , "");
这个逻辑在 css3
的情况下失败。请建议我解决此问题的正确方法。
注意:我正在使用 Java 7
我查看了以下帖子,但找不到任何解决方案:
- Java String.replaceAll regex
- java String.replaceAll regex question
- Java 1.3 String.replaceAll() , replacement
尝试将(^(11)(?:,))|((?<=,)(11)(?:,))|(,11$)
表达为replaceAll
:
final String regexp = MessageFormat.format("(^({0})(?:,))|((?<=,)({0})(?:,))|(,{0}$)", elimiateUserId)
String result = css#.replaceAll(regexp, "") //for all cases.
这是一个例子: https://regex101.com/r/LwJgRu/3
您可以在 Java 8:
中使用 Stream APIint elimiateUserId = 11;
String css1 = "11,22,33,44,55";
String css1Result = Stream.of(css1.split(","))
.filter(value -> !String.valueOf(elimiateUserId).equals(value))
.collect(Collectors.joining(","));
// css1Result = 22,33,44,55
这应该有效
replaceAll("(11,|,11)", "")
至少当你能保证没有311的时候,或者,113左右
如果你想使用正则表达式,你可以使用(记得正确转义为 java 字符串文字)
,\b11\b|\b11\b,
这将确保 11 不会由于单词边界而被匹配为另一个数字的一部分,并且只会匹配和删除一个逗号(如果存在两个逗号)。
您可以一次使用两个替换,例如:
int elimiateUserId = 11;
String result = css#.replace("," + elimiateUserId , "").replace(elimiateUserId + ",", "");
如果您的字符串类似于 ,11
,则第一个替换会将其替换为空字符串
如果您的字符串类似于 11,
,则第二个替换会将其替换为空
结果
11,22,33,44,55 -> 22,33,44,55
22,33,11,44,55 -> 22,33,44,55
22,33,44,55,11 -> 22,33,44,55
你可以像这样构建一个正则表达式
^11,|,11\b
将匹配字符串开头的 11,
(^11,
) 或 (|
) ,11
后面没有任何其他单词 char (,11\b
).
参见regex demo。
int elimiate_user_id = 11;
String pattern = "^" + elimiate_user_id + ",|," + elimiate_user_id + "\b";
System.out.println("11,22,33,44,55,111".replaceAll(pattern, "")); // => 22,33,44,55,111
System.out.println("22,33,11,44,55,111".replaceAll(pattern, "")); // => 22,33,44,55,111
System.out.println("22,33,44,55,111,11".replaceAll(pattern, "")); // => 22,33,44,55,111
我认为维护一个白名单比较安全,然后将其作为参考进行进一步的更改。
List<String> whitelist = Arrays.asList("22", "33", "44", "55");
String s = "22,33,44,55,11";
String[] sArr = s.split(",");
StringBuilder ids = new StringBuilder();
for (String id : sArr) {
if (whitelist.contains(id)) {
ids.append(id).append(", ");
}
}
String r = ids.substring(0, ids.length() - 2);
System.out.println(r);
试试这个:
String result = css#.replaceAll("," + elimiateUserId, "")
.replaceAll(elimiateUserId + "," , "");
String result = css#.replaceAll("," + eliminate_user_id + "\b|\b" + eliminate_user_id + ",", '');
这里的正则表达式是:
, A leading comma.
eliminate_user_id I assumed the missing 'n' here was a typo.
\b Word boundary: word/number characters end here.
| OR
\b Word boundary: word/number characters begin here.
eliminate_user_id again.
, A trailing comma.
单词边界标记,匹配 "word" 的开头或结尾,是这里的魔法。这意味着 11 将匹配这些字符串:
11,22,33,44,55
22,33,11,44,55
22,33,44,55,11
但不是这些字符串:
111,112,113,114
411,311,211,111
不过,还有一种更简洁的方法:
String result = css#.replaceAll("(,?)\b" + eliminate_user_id + "\b(?(1)|,)", "");
这里的正则表达式是:
( A capturing group - what's in here, is in group 1.
,? An optional leading comma.
) End the capturing group.
\b Word boundary: word/number characters begin here.
eliminate_user_id I assumed the missing 'n' here was a typo.
\b Word boundary: word/number characters end here.
(?(1) If there's something in group 1, then require...
| ...nothing, but if there was nothing, then require...
, A trailing comma.
) end the if.
此处的 "if" 部分有点不寻常 - 您可以在此处找到有关正则表达式条件的更多信息:http://www.regular-expressions.info/conditional.html
我不确定 Java 是否支持正则表达式条件。这里的一些帖子 (Conditional Regular Expression in Java?) 表明它没有 :(
旁注:为了性能,如果列表很长并且要执行的删除操作非常多,最明显的选择是 运行 上面一行中的每个要删除的数字:
String css = "11,22,33,44,55,66,77,88,99,1010,1111,1212,...";
Array<String> removals = ["11", "33", "55", "77", "99", "1212"];
for (i=0; i<removals.length; i++) {
css = css.replaceAll("," + removals[i] + "\b|\b" + eliminate_user_id + ",", "");
}
(代码未测试:此处无法访问 Java 编译器)
这将足够快(从 n 个 ID 的字符串中删除 m 的最坏情况大约为 O(m*n)),但我们也许可以做得更好。
一种是将正则表达式构建为 \b(11,42,18,13,123,...etc)\b
- 即让正则表达式同时搜索所有要删除的 ID。从理论上讲,这种缩放比例更差一些,在每种情况下都以 O(m*n) 缩放,而不是最坏的情况,但实际上应该快得多。
String css = "11,22,33,44,55,66,77,88,99,1010,1111,1212,...";
Array<String> removals = ["11", "33", "55", "77", "99", "1212"];
String removalsStr = String.join("|", removals);
css = css.replaceAll("," + removalsStr + "\b|\b" + removalsStr + ",", "");
但另一种方法可能是构建长字符串中 ID 的哈希表,然后从哈希表中删除所有 ID,然后将剩余的哈希表键连接回字符串。由于哈希表查找对于稀疏哈希表来说实际上是 O(1),这使得这个规模与 O(n) 成正比。不过,这里的权衡是该哈希表的额外内存。
(如果没有 java 编译器,我不认为我可以做这个版本。我不会推荐这种方法,除非你有一个 VAST(数千)ID 列表要删除,无论如何,因为这将是更丑陋和更复杂的代码。
如果您需要使用 Regex 的解决方案,那么下面的方法非常有效。
int elimiate_user_id = 11;
String css1 = "11,22,33,44,55";
String css2 = "22,33,11,44,55";
String css3 = "22,33,44,55,11";
String resultCss=css1.replaceAll(elimiate_user_id+"[,]*", "").replaceAll(",$", "");
我处理您想要的所有类型的输入。