有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java中带有变量的正则表达式

我有一个变量v,它可能在一个字符串中连续出现多次。我想让所有连续的v变成一个v。例如:

String s = "Hello, world!";
String v = "l";

正则表达式会变成“你好,世界!”进入“Helo,世界!”

所以我想做一些类似的事情

s = s.replaceAll(vv+, v)

但很明显,这是行不通的。想法


共 (5) 个答案

  1. # 1 楼答案

    让我们迭代开发解决方案;在每一步中,我们都会指出问题所在并加以解决,直到找到最终答案

    我们可以从以下内容开始:

    String s = "What???? Impo$$ible!!!";
    String v = "!";
    
    s = s.replaceAll(v + "{2,}", v);
    System.out.println(s);
    // "What???? Impo$$ible!"
    

    {2,}是有限重复的正则表达式语法,在本例中表示“至少2个”

    碰巧,上面的工作是因为!不是regex元字符。让我们看看如果我们尝试以下方法会发生什么:

    String v = "?";
    
    s = s.replaceAll(v + "{2,}", v);
    // Exception in thread "main" java.util.regex.PatternSyntaxException:       
    // Dangling meta character '?'
    

    解决此问题的一种方法是使用Pattern.quote,这样v就可以按字面意思理解为:

    s = s.replaceAll(Pattern.quote(v) + "{2,}", v);
    System.out.println(s);
    // "What? Impo$$ible!!!"
    

    事实证明,这不是我们唯一需要担心的事情:在替换字符串中,\$也是特殊的元字符。这就解释了为什么我们会遇到以下问题:

    String v = "$";
    s = s.replaceAll(Pattern.quote(v) + "{2,}", v);
    // Exception in thread "main" java.lang.StringIndexOutOfBoundsException:
    // String index out of range: 1
    

    由于我们希望v被字面理解为替换字符串,因此我们使用Matcher.quoteReplacement如下所示:

    s = s.replaceAll(Pattern.quote(v) + "{2,}", Matcher.quoteReplacement(v));
    System.out.println(s);
    // "What???? Impo$ible!!!"
    

    最后,重复比串联具有更高的优先级。这意味着:

    System.out.println(  "hahaha".matches("ha{3}")    ); // false
    System.out.println(  "haaa".matches("ha{3}")      ); // true
    System.out.println(  "hahaha".matches("(ha){3}")  ); // true
    

    因此,如果v可以包含多个字符,那么您应该在应用重复之前对其进行分组。在这种情况下,您可以使用非捕获组,因为您不需要创建反向引用

    String s = "well, well, well, look who's here...";
    String v = "well, ";
    s = s.replaceAll("(?:" +Pattern.quote(v)+ "){2,}", Matcher.quoteReplacement(v));
    System.out.println(s);
    // "well, look who's here..."
    

    摘要

    • 要匹配可能包含正则表达式元字符的任意文字字符串,请使用^{}
    • 要替换为可能包含替换元字符的任意文字字符串,请使用^{}

    参考文献


    奖励材料

    以下示例使用不情愿重复、捕获组和反向引用,并混合使用不区分大小写的匹配:

        System.out.println(
            "omgomgOMGOMG???? Yes we can! YES WE CAN! GOAAALLLL!!!!"
                .replaceAll("(?i)(.+?)\\1+", "$1")
        );
        // "omg? Yes we can! GOAL!"
    

    相关问题

    参考文献

  2. # 2 楼答案

    使用x{2,}至少两次匹配x

    为了能够用正则表达式的特殊含义替换字符,可以使用^{}

    String part = Pattern.quote(v);
    s = s.replaceAll(part + "{2,}", v);
    

    要替换长度超过一个字符的内容,请使用非捕获组:

    String part = "(?:" + Pattern.quote(v) + ")";
    s = s.replaceAll(part + "{2,}", v);
    
  3. # 3 楼答案

    s = s.replaceAll (v + "+", v)
    
  4. # 4 楼答案

    对于Java中的正则表达式,请确保使用Pattern.quoteMatcher.quoteReplacement

    package com.example.test;
    
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    public class Regex2 {
        static public void main(String[] args)
        {
            String s = "Hello, world!";
            String v = "l";
    
            System.out.println(doit(s,v));
    
            s = "Test: ??r??r Solo ??r Frankenstein!";
            v = "??r";
    
            System.out.println(doit(s,v));
    
        }
    
        private static String doit(String s, String v) 
        {
            Pattern p = Pattern.compile("(?:"+Pattern.quote(v)+"){2,}");
    
            Matcher m = p.matcher(s);
            StringBuffer sb = new StringBuffer();
            while (m.find())
            {
                m.appendReplacement(sb, Matcher.quoteReplacement(v));
            }
            m.appendTail(sb);
            return sb.toString();
        }
    }
    
  5. # 5 楼答案

    您需要连接两个“v”字符串

    试试s = s.replaceAll(v + v + "+", v)