【问题标题】:Regex in Java not working while same regex is working in shellJava中的正则表达式不起作用,而相同的正则表达式在shell中工作
【发布时间】:2016-08-01 12:49:20
【问题描述】:

我想用${variable}$替换所有:variable(以:开头的单词)。

例如,

  • :aks_num${aks_num}$

  • :brn_num${brn_num}$

以下是我的代码,它不起作用:

public static void main(String[] argv) throws Exception 
{
    CharSequence chSeq = "AND ((:aks_num = -1) OR (aks_num = :aks_num AND ((:brn_num = -1) OR (brn_num = :brn_num))))";

    // replaceAll also not working
    //String s = chSeq.replaceAll(":\\([a-z_]*\\)","\\${ $1 \\}$");

    Pattern p = Pattern.compile(":\\([a-z_]*\\)");
    Matcher m = p.matcher(chSeq);

    if (m.find()) {
         System.out.println("Found value: " + m.group(0) );
         System.out.println("Found value: " + m.group(1) );
         System.out.println("Found value: " + m.group(2) );
      } else {
         System.out.println("NO MATCH");
      }
}

在 shell 脚本中,以下正则表达式完美运行:

s/:\([a-z_]*\)/${\1}$/g

【问题讨论】:

标签: java regex shell


【解决方案1】:

:\\([a-z_]*\\)(带转义括号)表示您要匹配 :(aks_num) 之类的表达式。显然,输入字符串中没有这样的表达式。这就解释了为什么没有匹配项。

相反,如果您想使用括号来捕获某些变量,则不应转义括号。

例子:

CharSequence chSeq = "AND ((:aks_num = -1) OR (aks_num = :aks_num AND ((:brn_num = -1) OR (brn_num = :brn_num))))";
Pattern p = Pattern.compile(":([a-z_]*)");
Matcher m = p.matcher(chSeq);

while (m.find()) {
  System.out.println("Found value: " + m.group(0)+". Captured : "+m.group(1));
}

输出:

Found value: :aks_num. Captured : aks_num
Found value: :aks_num. Captured : aks_num
Found value: :brn_num. Captured : brn_num
Found value: :brn_num. Captured : brn_num

【讨论】:

  • @Shafizadeh 一些金牌很容易获得,但这不是我的目标 :)
【解决方案2】:
CharSequence chSeq = "AND ((:aks_num = -1) OR (aks_num = :aks_num AND ((:brn_num = -1) OR (brn_num = :brn_num))))";

// replaceAll also not working
//String s = chSeq.replaceAll(":\\([a-z_]*\\)","\\${ $1 \\}$");

Pattern p = Pattern.compile(":(\\w+)");
Matcher m = p.matcher(chSeq);

while (m.find()) {
     System.out.println("Found value: " + m.group(1) );
}

Ideone Demo

使用replaceAll 工作正常

Pattern p = Pattern.compile("(:\\w+)");
Matcher m = p.matcher(x);
x = m.replaceAll("\\${$1}\\$");

【讨论】:

    【解决方案3】:

    你不需要转义括号,所以

    Pattern.compile(":([a-z_]*)");
    

    应该可以。

    【讨论】:

      【解决方案4】:

      我相信您对不同于常规 sed 语法的 Java 正则表达式语法感到困惑。您不需要转义括号以使它们成为“特殊”分组运算符。反之亦然,在 Java 中,当您转义括号时,它们开始匹配文字 () 符号。

      在替换模式中,$ 必须转义,以便正则表达式引擎用文字 $ 符号替换,但您不需要在那里转义大括号。

      所以,只需使用

      .replaceAll(":([a-z_]+)", "\\${$1}\\$")
      

      IDEONE demo

      我建议使用 + 量词,因为我怀疑您是否需要匹配 : 后跟空格或数字 - 任何非字母。

      顺便说一句,Java 中不需要任何 /g 标志,因为 replaceAll 将用提供的替换模式替换 所有 匹配项。

      注意:您可以进一步调整模式以匹配所有字母/数字/下划线与":(\\w+)"。或者只是字母数字/下划线:":([\\p{Alnum}_]+)"

      【讨论】:

      • @Shafizadeh:你在想这个,见s/:\([a-z_]*\)/${\1}$/g
      • 是的,也许只有 a-z 适合 OP。无论如何,我认为您的 NOTE 就足够了。
      猜你喜欢
      • 2020-07-08
      • 2016-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多