{m} {n}("恰好n次"两次)如何工作?

Duk*_*ing 77 java regex

所以,某种方式(玩弄),我发现自己有一个正则表达式 \d{1}{2}.

从逻辑上讲,对我而言,它应该意味着:

(一个数字恰好一次)恰好两次,即一个数字恰好两次.

但事实上,它似乎只是意味着"一个数字恰好一次"(因此忽略了 {2}).

String regex = "^\\d{1}{2}$"; // ^$ to make those not familiar with 'matches' happy
System.out.println("1".matches(regex)); // true
System.out.println("12".matches(regex)); // false
Run Code Online (Sandbox Code Playgroud)

使用可以看到类似的结果 {n}{m,n}或类似.

为什么会这样?它是在regex/Java文档中明确说明的,还是只是Java开发人员即时做出的决定,还是它可能是一个bug?

或者它实际上没有被忽略,它实际上完全意味着什么呢?

并不重要,但它不是全面的正则表达式行为,Rubular做了我所期望的.

注意 - 标题主要用于想要了解其工作原理(不是为什么)的用户的可搜索性.

pie*_*t.t 108

IEEE标准1003.1说:

多个相邻复制符号('*'和间隔)的行为会产生不确定的结果.

因此,每个实施都可以随心所欲,只是不要依赖任何具体的......

  • @STTLCU嗯,正式与非正式遵守或不遵守之间存在差异.正式遵循意味着它可以被引用作为源,否则它仍然是一个很好的参考,但并不一定解释为什么Java会做它的功能. (3认同)
  • 我很确定这个标准适用于POSIX BRE和ERE,而且它与Java正则表达式没什么关系.Java甚至声称不支持ERE或BRE!如果有的话,这里应该引用Unicode正则表达式http://unicode.org/reports/tr18/. (3认同)
  • 是的,因为输出结果是标准有效的,即:它可以做任何事情. (2认同)
  • @Dukeling我也相信.注意`System.out.println("".matches("^ {1} $"));`也返回`true`.我敢打赌,如果Java找不到重复的有效模式,它将重复"null"而不是抛出错误(匹配字符串中的任何位置).另外,你使用基于Ruby的regex测试程序来实现Java! (2认同)

Lie*_*ers 76

当我使用Java正则表达式语法在RegexBuddy中输入正则表达式时,它会显示以下消息

量词必须前面有一个可以重复的标记«{2}»

更改正则表达式以显式使用分组^(\d{1}){2}可以解决该错误并按预期工作.


我假设java正则表达式引擎只是忽略了错误/表达式,并使用到目前为止编译的内容.

编辑

在参考IEEE-标准@ piet.t的答案似乎支持这一假设.

编辑2 (感谢@fncomp)

为了完整性,通常会使用(?:)以避免捕获组.然后完整的正则表达式成为^(?:\d{1}){2}

  • 不会'^(:?\ d {1}){2} $`更准确地再现意图?(为了避免捕获.) (4认同)
  • @fncomp - 会的,这也是我使用的。不过有一个小错别字——应该是“(?:)” (2认同)

Kob*_*obi 10

科学方法:
单击模式以查看regexplanet.com上的示例,然后单击绿色Java按钮.

  • 你已经展示了\d{1}{2}匹配"1",但是不匹配"12",所以我们知道它不会被解释为(?:\d{1}){2}.
  • 尽管如此,1是一个无聊的数字,{1} 可能会被优化掉,让我们尝试更有趣的事情:
    \d{2}{3}.这仍然只匹配两个字符(不是六个),{3}被忽略.
  • 好.有一种简单的方法可以查看正则表达式引擎的功能.它捕获了吗?
    让我们试试(\d{1})({2}).奇怪的是,这是有效的.第二组$2捕获空字符串.
  • 那么为什么我们需要第一组呢?怎么样({1})?仍然有效.
  • 只是{1}?没问题.
    看起来Java在这里有点奇怪.
  • 大!所以{1}是有效的.我们知道Java的扩展*,并+{0,0x7FFFFFFF}{1,0x7FFFFFFF},所以会*+工作?没有:

    在索引0
    +
    ^ 附近悬挂元字符'+'

    验证必须在之前进行*+进行扩展.

我没有在规范中找到任何解释的东西,看起来量词必须至少在一个字符,括号或括号之后出现.

大多数这些模式被其他正则表达式的味道视为无效,并且有充分的理由 - 它们没有意义.