繁体   English   中英

Java使用正则表达式替换多重字符

[英]Java replace multiplet characters using regular expression

我正在尝试编写一个字符串替换方法,它可以工作,但在同一字符串上使用多个替换方法看起来很糟糕。 很确定我可以在这里使用正则表达式。

        List<String>  strng = Collections.singletonList(answer.toString()
                .replace(",", "/")
                .replace("#"", " ")
                .replace("*", "")
                .replace("&", "")
                .replace("]", ""));

我只想使用 1 个 replace() 或 replaceAll() 方法。 总之试图构造一个正则表达式来替换这些字符,#*&]

简单的正则表达式替换操作不支持在一个操作中进行条件替换。

启用最新的 JDK 和“预览功能”后,您可以执行以下操作

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("[*&\\\\]]", "")替换,但.replaceAll("[*&\\\\]]", "") ,使用正则表达式引擎不一定比多个纯文本替换更有效操作。

可以使用正则表达式将最后三个调用替换为一个调用,如下所示:

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

如果您碰巧使用 Apache Commons 库,则可以使用方法replaceChars

replaceChars(String str, String searchChars, String replaceChars)

来自 StringUtils 类。 但仅仅因为包含库的一种方法在我看来是多余的。

String str = "foobar,123#xyz*abc&def]";
String res = StringUtils.replaceChars(str, ",#*&]", "/ ");
System.out.println(res);

//output : foobar/123 xyzabcdef 

把它分成两部分。

  1. 删除所有字符(替换为空字符串 ( "" )。使用String::replaceAll和正则表达式定义要删除的一组字符: answer.replaceAll("[*&\\\\]]", "")
  2. 准备两个包含替换之前之后的字符的字符串。 强制两个字符串的长度相同,并且每个字符替代内容恰好与彼此(根据你的问题)的规则。 为此,您可以使用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);

如您所见, IntStream.range(int, int)很方便。 此外,您可以使用删除结果本身作为reduce 操作的identity


免责声明:该解决方案仅适用于删除大量字符以避免重复。 否则, String::replace就更合适了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM