英文:
Java replace multiplet characters using regular expression
问题
我正在尝试编写一个字符串替换方法,它可以工作,但在同一个字符串上使用多个替换方法看起来不太好。相信我可以在这里使用正则表达式。
List<String> strng = Collections.singletonList(answer.toString()
.replaceAll("[,]", "/")
.replaceAll("[#&]", " ")
.replaceAll("[*]", "")
.replaceAll("&", "")
.replaceAll("]", ""));
我想只使用一个replace()
或者replaceAll()
方法。简而言之,尝试构造一个正则表达式来替换这些字符 , # * & ]。
英文:
I am trying to write a String replace method , it works but looks bad using multiple replace methods on same string. Pretty sure I could use a regular expression here.
List<String> strng = Collections.singletonList(answer.toString()
.replace(",", "/")
.replace("#"", " ")
.replace("*", "")
.replace("&", "")
.replace("]", ""));
I would like to use just 1 replace() or replaceAll() method.
in short trying to construct a Regular expression to replace these characters , # * & ]
答案1
得分: 1
简单的正则表达式替换操作不支持在一次操作中进行条件替换。
使用最近的JDK并启用“preview-features”,您可以这样做:
static final Pattern SPECIAL_CHARS = Pattern.compile("[,#*&\\]]");
List<String> strng = List.of(
SPECIAL_CHARS.matcher(answer.toString())
.replaceAll(mr -> switch(mr.group().charAt(0)) {
case ',' -> "/";
case '#' -> " ";
default -> "";
}));
一个兼容Java 8的等效方法会更详细:
static String replaceSpecialChars(String input) {
Matcher m = SPECIAL_CHARS.matcher(input);
if(!m.find()) return input;
StringBuffer sb = new StringBuffer(input.length());
do {
String s;
switch(m.group().charAt(0)) {
case ',': s = "/"; break;
case '#': s = " "; break;
default: s = "";
}
m.appendReplacement(sb, s);
} while(m.find());
return m.appendTail(sb).toString();
}
尽管这些方法可以一次完成操作,但您需要一个非常大的输入字符串才能从中受益。否则,您的一系列普通(非正则表达式)replace
调用可能更有效。您甚至可以将前两个替换从String
更改为char
的替换,即.replace(',', '/').replace('#', ' ')
。由于其他三个具有相同的替换,它们可以被单个.replaceAll("[*&\\]]", "")
替换,但正如前面所说,使用正则表达式引擎不一定比多个纯文本替换操作更有效。
英文:
Simple regex replacement operations do not support conditional replacements in one operation.
With a recent JDK and “preview-features” enabled, you could do as
static final Pattern SPECIAL_CHARS = Pattern.compile("[,#*&\\]]");
List<String> strng = List.of(
SPECIAL_CHARS.matcher(answer.toString())
.replaceAll(mr -> switch(mr.group().charAt(0)) {
case ',' -> "/";
case '#' -> " ";
default -> "";
}));
A Java 8 compatible equivalent would be more elaborated:
static String replaceSpecialChars(String input) {
Matcher m = SPECIAL_CHARS.matcher(input);
if(!m.find()) return input;
StringBuffer sb = new StringBuffer(input.length());
do {
String s;
switch(m.group().charAt(0)) {
case ',': s = "/"; break;
case '#': s = " "; break;
default: s = "";
}
m.appendReplacement(sb, s);
} while(m.find());
return m.appendTail(sb).toString();
}
While these approaches perform the operation in one go, you’d need a really large input string to draw a benefit from that. Otherwise, your chain of plain (non-regex) replace
calls is likely to be more efficient. You could even replace the first two from String
to char
replacements, i.e. .replace(',', '/').replace('#', ' ')
. Since the other three have the same replacement, they could get replaced by a single .replaceAll("[*&\\]]", "")
but as said, using the regex engine is not necessarily more efficient than multiple plain text replacement operations.
答案2
得分: 0
以下是翻译好的部分:
最后三个调用可以使用正则表达式进行替换,如下所示:
List<String> strng = Collections.singletonList(answer.toString()
.replace(",", "/")
.replace("#", " ")
.replaceAll("[\\*&\\]]", ""));
正则表达式 [\\*&\\]]
指定了任何一个 *
、&
或 ]
。从 这里 了解更多关于字符类的信息。
演示:
public class Main {
public static void main(String[] args) {
String str = "Hello,Hi#Bye*World&Welcome]Good";
System.out.println(str
.replace(",", "/")
.replace("#", " ")
.replaceAll("[\\*&\\]]", ""));
}
}
输出:
Hello/Hi ByeWorldWelcomeGood
英文:
The last three calls can be replaced with one call by using regex as shown below:
List<String> strng = Collections.singletonList(answer.toString()
.replace(",", "/")
.replace("#", " ")
.replaceAll("[\\*&\\]]", ""));
The regex, [\\*&\\]]
specifies any of *
, &
or ]
. Learn more about character classes from here.
Demo:
public class Main {
public static void main(String[] args) {
String str = "Hello,Hi#Bye*World&Welcome]Good";
System.out.println(str
.replace(",", "/")
.replace("#", " ")
.replaceAll("[\\*&\\]]", ""));
}
}
Output:
Hello/Hi ByeWorldWelcomeGood
答案3
得分: 0
如果您恰好使用Apache Commons库,您可以使用StringUtils类中的方法replaceChars:
replaceChars(String str, String searchChars, String replaceChars)
但仅仅因为一个方法而导入整个库,在我看来有些多余。
String str = "foobar,123#xyz*abc&def]";
String res = StringUtils.replaceChars(str, ",#*&]", "/ ");
System.out.println(res);
//输出:foobar/123 xyzabcdef
英文:
If you happen to use the Apache Commons library you can use the method replaceChars
replaceChars(String str, String searchChars, String replaceChars)
from the StringUtils class. But just because of the one method to include the library would be superfluous in my opinion.
String str = "foobar,123#xyz*abc&def]";
String res = StringUtils.replaceChars(str, ",#*&]", "/ ");
System.out.println(res);
//output : foobar/123 xyzabcdef
答案4
得分: 0
将其分成两个部分。
- 删除所有字符(用空字符串替换(
""
)。使用String::replaceAll
与一个正则表达式定义的一组要删除的字符:answer.replaceAll("[*&\\]]", "")
。 - 准备两个字符串,分别包含替换之前和之后的字符。确保这两个字符串的长度相同,并且每个字符都恰好被另一个字符替代(根据您的问题)。您可以使用
String[]
来实现这个目的。遍历字符并在原始字符串中进行替换。
String[] mapping = {",#", " "};
// 下面的代码保持不变,不管有多少次替换
String newAnswer = IntStream.range(0, mapping[0].length()).boxed().reduce(
answer.replaceAll("[*&\\]]", ""),
(str, i) -> str.replace(mapping[0].charAt(i), mapping[1].charAt(i)),
(l, r) -> l);
如您所见,IntStream.range(int, int)
很方便。此外,您可以将删除结果本身用作 reduce 操作的“identity”。
**免责声明:**此解决方案仅适用于需要删除大量字符以避免重复的情况。否则,一系列的 String::replace
更加合适。
英文:
Divide it into two parts.
- Remove all the characters (replacement with an empty string (
""
). UseString::replaceAll
with a Regex defining a set of characters to be removed:answer.replaceAll("[*&\\]]", "")
. - Have two strings ready containing the characters before replacement and after. Enforce the same length of both strings and a rule that each character is subsituted with exactly one another (according to your question). You can use
String[]
for this purpose. Iterate through the characters and replace them in the original string.
String[] mapping = {",#", " "};
// The advantage is the code below remains the same regardles the number or replacements
String newAnswer = IntStream.range(0, mapping[0].length()).boxed().reduce(
answer.replaceAll("[*&\\]]", ""),
(str, i) -> str.replace(mapping[0].charAt(i), mapping[1].charAt(i)),
(l, r) -> l);
As you can see, IntStream.range(int, int)
comes handy. Moreover, you can use the removal result itself as an identity
of the reduce operation.
Disclaimer: The solution is suitable only for a large set of characters to be removed to avoid repetitions. Otherwise a chain of String::replace
is more than suitable.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论