【问题标题】:Non capturing group in Java Scanner is ignoredJava Scanner 中的非捕获组被忽略
【发布时间】:2020-02-09 08:33:13
【问题描述】:

我试图让扫描仪在每个 @ 符号上拆分一个字符串,除非转义(或在行首)

我的正则表达式: (?:[^\\])@

(?:            // Start of non-capturing group (0)
  [            // Match any characters in square brackets [
    ^\\        // Match any non-\ character.
  ]            // ]
)              // End of non-capturing group (0)
@              // Match literal '@'

据我了解,这应该符合我的意图。

但是,在扫描仪中使用此模式时,它只是忽略了非捕获组不应计入分隔符的事实,只是为了匹配,分隔符(要删除/拆分的部分)应该是只是 '@'。因此对于以下示例字符串:“Hello@World”,结果必须是 ["Hello", "World"]。

除了运行以下代码示例:

private static void test() {
    try (Scanner sc = new Scanner("test@here")) {
        sc.useDelimiter("(?:[^\\\\])@"); // Every unescaped @ sign.
        while (sc.hasNext()) {
            String token = sc.next();
            System.out.println(token);
        }
    }   
}

产量:

tes
here

而不是预期的:

test
here

【问题讨论】:

  • 如果你使用它,那么转义将不起作用,例如"Hello\@World" 不应该在 @ 上定界,但 "Hello@World" 应该。检查 regex101,使用我和你的分隔符来查看它捕获的内容的区别。

标签: java regex java.util.scanner delimiter


【解决方案1】:

分隔符被认为是整个匹配,不考虑组,捕获或不捕获。

你需要的是一个lookbehind模式,这里的语法更容易使用否定的lookbehind。

sc.useDelimiter("(?<!\\\\)@");

【讨论】:

  • 好吧,你写得更快了。但是我在再次阅读 regex101 后认真地找到了解决方案。谢谢您的帮助。我认为非捕获的名称非常令人困惑,我根本没有考虑负面的后视。
  • 我很少使用负面的lookbehind,因为这些天我主要使用JavaScript,当代码必须在网络浏览器上运行时,目前只有Chrome支持lookbehind。
  • 那么你用什么来代替lookbehind?非捕获的东西?就像非捕获总是得到服从一样。不会像在 java 中那样偷偷地忽略。
  • 我最终不得不使用捕获组来进行回顾,然后再次将它们拼凑在一起。
【解决方案2】:

扫描程序不使用捕获组like replace all

相反,您应该使用负面的看法。所以你的模式应该是这样的:

(?<!\\)@

这也清除了所需的否定类。

其中: 被简单地替换为<! 为了使非捕获组,组的负面外观。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-08
    • 2010-12-17
    • 1970-01-01
    • 1970-01-01
    • 2013-12-04
    • 2019-12-31
    • 2016-01-28
    • 1970-01-01
    相关资源
    最近更新 更多