有一个Java Regex问题:给定一个字符串,如果"*"位于字符串的开头或结尾,请保留它,否则删除它.例如:
*
- > *
**
- > **
*******
- > **
*abc**def*
- > *abcdef*
答案是:
str.replaceAll("(^\\*)|(\\*$)|\\*", "$1$2");
Run Code Online (Sandbox Code Playgroud)
我在我的机器上尝试了答案,但它确实有效.但我不知道它是如何工作的.
根据我的理解,所有匹配的子串应该替换为$1$2
.但是,它的工作原理如下:
(^\\*)
替换为$1
,(\\*$)
替换为$2
,\\*
换成空的.有人能解释它是如何工作的吗?更具体地说,如果|
表达式之间存在,那么如何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
有关更多信息,请参阅捕获组
您可以在正则表达式中使用环视:
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)