带有后引用的Java String.replaceAll()

Jef*_*rey 12 java regex

有一个Java Regex问题:给定一个字符串,如果"*"位于字符串的开头或结尾,请保留它,否则删除它.例如:

  1. * - > *
  2. ** - > **
  3. ******* - > **
  4. *abc**def* - > *abcdef*

答案是:

str.replaceAll("(^\\*)|(\\*$)|\\*", "$1$2");
Run Code Online (Sandbox Code Playgroud)

我在我的机器上尝试了答案,但它确实有效.但我不知道它是如何工作的.

根据我的理解,所有匹配的子串应该替换为$1$2.但是,它的工作原理如下:

  1. (^\\*)替换为$1,
  2. (\\*$)替换为$2,
  3. \\* 换成空的.

有人能解释它是如何工作的吗?更具体地说,如果|表达式之间存在,那么如何String.replaceAll()使用后向引用?

先感谢您.

Sal*_*eem 25

我将尝试解释正则表达式中发生的事情.

str.replaceAll("(^\\*)|(\\*$)|\\*", "$1$2");
Run Code Online (Sandbox Code Playgroud)

$1表示(^\\*) $2代表第二组的第一组(\\*$)

当你打电话时str.replaceAll,你实际上是在捕捉两个组以及其他所有内容,但在更换时,将捕获的文本替换为两个组中捕获的内容.

例: *abc**def* --> *abcdef*

正则表达式是从字符串开始*,它将放入$1组中,接下来它将继续查找,直到它*在组的末尾找到并存储它#2.现在当更换它时将消除*除存储在$1或之外的所有内容$2

有关更多信息,请参阅捕获组


anu*_*ava 6

您可以在正则表达式中使用环视:

String repl = str.replaceAll("(?<!^)\\*+(?!$)", "");
Run Code Online (Sandbox Code Playgroud)

正则表达式演示

正则表达式分解:

(?<!^)   # If previous position is not line start
\\*+     # match 1 or more *
(?!$)    # If next position is not line end
Run Code Online (Sandbox Code Playgroud)

OP的正则表达式是:

(^\*)|(\*$)|\*
Run Code Online (Sandbox Code Playgroud)

它使用 2 个捕获组,一个用于*开始,另一个用于*结束,并在替换中使用反向引用。这可能在这里可行,但对于较大的字符串来说,完成速度会更慢,如本演示中采取的步骤所示。即209 步与使用环视的48步相比。

OP 正则表达式的另一个较小的改进是使用量词

(^\*)|(\*$)|\*+
Run Code Online (Sandbox Code Playgroud)