[英]Why the zero-length character always remains at the end of the source string for java regex pattern a?
Pattern pattern = Pattern.compile("a?");
Matcher matcher = pattern.matcher("a");
while(matcher.find()){
System.out.println(matcher.start()+"["+matcher.group()+"]"+matcher.end());
}
输出:
0[a]1
1[]1
为什么在有一个字符作为匹配器的情况下这给了我两个输出。
我注意到,对于此模式,它始终在源字符串的末尾提供零长度。 例如:当来源是“ abab”时,它给出
0[a]1
1[]1
2[a]3
3[]3
4[]4
正则表达式的特殊字符?
(问号)表示“将先前的事物匹配零或一次”。
由于您是在while循环中进行匹配( while (matcher.find()) {...
),因此它将找到表达式的两个匹配项:一次出现“ a”(位置0,字符串“ a”),一次出现零“ a”的值(在位置1,结尾处为空字符串)。
因此,这是您的代码段匹配的内容(开始/结束索引由X/Y
表示):
String: " a b a b "
├─┼─┼─┼─┤
Index: 0 1 2 3 4
Match: ╰┬╯ ╰┬╯ ╰- the empty string 4/4 (zero occurrences of "a").
|| |╰- the empty string 3/3 (zero occurrences of "a").
|| ╰ the string "a" 2/3 (one occurrence of "a").
|╰ the empty string 1/1 (zero occurrences of "a").
╰ the string "a" 0/1 (one occurrence of "a").
由于表达式是贪婪的,因此它在位置0/0或2/2处不匹配,这意味着只要不使下一个字符无效,它将尝试考虑下一个字符(在位置0 / 1、2 / 3处)。匹配(不是),因此将其跳过。 举例说明,是否将字符串"bbbb"
与模式a?
匹配a?
那么您将获得五个空字符串,每个空字符串在开头,结尾和每个字符之间都有一个。
a?
代表字符a
0或1 a
。
空字符串与出现的0相匹配。
匹配在您的情况下也是贪婪的,因此它首先匹配1个事件,然后匹配0个事件。
在abab
情况下,将其视为a[]ba[]b[]
,其中[]表示找到的空出现。 匹配程序在第一个b
的开头或之后找不到它,因为它可以在a
上贪婪地匹配。
在最后一个字符后匹配空白不是普遍的。
Vim编辑器具有以下行为:
缓冲之前:
aaaa
~
~
:s/x\?/y/g <- command
之后的缓冲:
yayaya
~
~
在aaaa
没有x
出现,但是x?
(默认在Vim中写为x\\?
)允许为空匹配。 该模式匹配字符串开头和所有字符之间的空白,但不能超过结尾。
例外是如果该行为空。 该命令将用单个y
替换空行。
我在自己的程序中实现了类似Vim的行为:
$ txr -c '@(bind result @(regsub #/x?/ "y" "aaaa"))'
result="yayayaya"
$ txr -c '@(bind result @(regsub #/x?/ "y" ""))'
result="y"
仅因为Vim很流行,如果有任何问题,我可以将其作为参考模型。 但这有点骇人听闻。 该逻辑有一个do .. while
循环,该循环允许处理传入的空字符串:
do {
/* regex match, extraction, substitution ... */
position++;
} while (position < length(input))
因此,如果起始位置为零,并且输入的长度为零,则执行一次循环,将正则表达式应用于空字符串。 但是,如果我们处理最后一个字符,则位置到达该长度,并且循环终止,而不处理空字符串。
最初,我在顶部进行了循环测试,因此它的行为类似于Vim,但在空输入情况下却没有,这与在空时匹配的正则表达式不匹配。
您正在使用的Java类的行为可能是这样实现的:
while (position <= length(input)) {
/* process regex */
position++;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.