Java 如何替换多个匹配的正则表达式

Java 如何替换多个匹配的正则表达式,java,regex,string,Java,Regex,String,我有一组正则表达式替换,需要应用于一组字符串 例如: 具有单个空格的所有多个空格(“\s{2,}”->”) 全部。后面跟着一个带有字符的字符。后跟空格,后跟字符(\。([a-zA-Z]-->“$1”) 所以我会有这样的东西: String s="hello .how are you?"; s=s.replaceAll("\\s{2,}"," "); s=s.replaceAll("\\.([a-zA-Z])",". $1"); .... s = s.replaceAll("\\s{2,

我有一组正则表达式替换,需要应用于一组字符串

例如:

  • 具有单个空格的所有多个空格
    (“\s{2,}”->”)
  • 全部。后面跟着一个带有字符的字符。后跟空格,后跟字符
    (\。([a-zA-Z]-->“$1”)
  • 所以我会有这样的东西:

    String s="hello     .how are you?";
    s=s.replaceAll("\\s{2,}"," ");
    s=s.replaceAll("\\.([a-zA-Z])",". $1");
    ....
    
    s = s.replaceAll("\\s{2,}|(\\.)(?=[a-zA-Z])", "$1 ");
    
    它可以工作,但是想象一下,我正在尝试替换一个长字符串上的100多个这样的表达式。不用说这有多慢

    所以我的问题是,是否有一种更有效的方法可以用一个replaceAll(或类似的东西,例如Pattern/Matcher)来概括这些替换

    我跟着


    但问题是我的正则表达式不是
    简单字符串

    您有以下2个
    replaceAll
    调用:

    s = s.replaceAll("\\s{2,}"," ");
    s = s.replaceAll("\\.([a-zA-Z])",". $1");
    
    您可以将它们组合成一个
    replaceAll
    ,如下所示:

    String s="hello     .how are you?";
    s=s.replaceAll("\\s{2,}"," ");
    s=s.replaceAll("\\.([a-zA-Z])",". $1");
    ....
    
    s = s.replaceAll("\\s{2,}|(\\.)(?=[a-zA-Z])", "$1 ");
    
    查看并修改它

    使用
    地图

    • 将数字分组为整数键
    • Lambdas作为值
    修改循环以检查匹配的组。然后使用该组编号获取替换lambda

    伪代码

    Map<Integer, Function<Matcher, String>> replacements = new HashMap<>() {{
        put(1, matcher -> "");
        put(2, matcher -> " " + matcher.group(2));
    }};
    
    String input = "lorem substr1 ipsum substr2 dolor substr3 amet";
    
    // create the pattern joining the keys with '|'. Need to add groups for referencing later
    String regexp = "(\\s{2,})|(\\.(?:[a-zA-Z]))";
    
    StringBuffer sb = new StringBuffer();
    Pattern p = Pattern.compile(regexp);
    Matcher m = p.matcher(input);
    
    while (m.find()) {
        //TODO change to find which groupNum matched
        m.appendReplacement(sb, replacements.get(m.group(groupNum)));
    }
    m.appendTail(sb);
    
    
    System.out.println(sb.toString());   // lorem repl1 ipsum repl2 dolor repl3 amet
    
    Map replacements=newhashmap(){{
    放置(1,匹配器->“”);
    put(2,matcher->“”+matcher.group(2));
    }};
    字符串输入=“lorem substr1 ipsum substr2 dolor substr3 amet”;
    //创建用“|”连接键的模式。需要添加组以供以后参考
    字符串regexp=“(\\s{2,})|(\\.(?:[a-zA-Z])”;
    StringBuffer sb=新的StringBuffer();
    Pattern p=Pattern.compile(regexp);
    匹配器m=p.Matcher(输入);
    while(m.find()){
    //TODO更改以查找匹配的groupNum
    m、 appendReplacement(sb,replacements.get(m.group(groupNum));
    }
    m、 (某人);
    System.out.println(sb.toString());//lorem repl1 ipsum repl2 dolor repl3 amet
    
    您可以使用一个大的正则表达式和。但是,您必须非常小心使用您的正则表达式,因为它可能会变得有些混乱,并可能遭受灾难性的回溯。@BoristheSpider如果我使用它,那么我就很难知道使用了哪个正则表达式。不,只需使用捕获组并检查其中有数据。@Boris假设我匹配了
    。A
    我如何知道这是否是使用
    \\([A-zA-Z])
    匹配的。如果您有一个模式,例如
    (A)|(B)
    ,那么您知道,当您获得匹配时,第一组或第二组将被填充-另一组将为空(禁用)。你可以用它来确定替换。这是一个很好的观察搭档,但不幸的是,还有许多其他规则不适合这种技术。我根据你所讨论的代码发布了答案。如果你展示更多的代码,那么我可以更好地判断可以做些什么来优化它。thx搭档,有100多条规则,显然是pointl要把它们全部加起来,还有一个
    ([a-zA-Z])\\-,([a-zA-Z])
    -->-
    $1-$2
    @nafas这是一个好的解决方案的基础,即使您的表达式是“复杂的”。如果您可以根据常见的替换表达式对所有正则表达式进行分组,那么使用regex替换来链式调用
    replaceAll()
    (如本例中所示),它将尽可能高效。例如
    s=s.replaceAll(\\s{2,}{124;(\\)(?=[a-zA-Z]),“$1”).replaceAll(“foo | bar | baz”,“qux”).replaceAll…;
    @Bohemian我同意,老实说,当anubhava成功地将两者结合起来时,我感到惊讶。这样我可以减少我正在使用的正则表达式的数量,但仍然需要很多repalcell等,我想单行程序或任何更复杂的东西都没有希望了。