繁体   English   中英

为什么对于Java regex模式a,零长度字符始终保留在源字符串的末尾?

[英]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上贪婪地匹配。

看一下

http://docs.oracle.com/javase/tutorial/essential/regex/quant.html

在“ 零长度匹配 ”部分下详细说明了您的情况

在最后一个字符后匹配空白不是普遍的。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM