Группа без захвата в Java Scanner игнорируется - PullRequest
2 голосов
/ 11 октября 2019

Я пытаюсь заставить сканер разделить строку на каждый символ @, за исключением экранирования (или в начале строки)

My RegEx: (?:[^\\])@

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

Исходя из моего понимания, это должно работать для моих намерений.

Однако при использовании этого шаблона в сканере он просто игнорирует тот факт, что не захватывающая группа не должна учитываться в качестве разделителя, просто для соответствиянапротив, разделитель (часть, которую необходимо удалить / разделить) должен быть просто '@'. Таким образом, для следующего примера String: "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

Ответы [ 2 ]

5 голосов
/ 11 октября 2019

Разделителем считается все совпадение, без учета групп, захвата или не захвата.

Вам нужен шаблон вида за кадром, а синтаксис здесь проще с отрицательным взглядом за спиной.

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

2 голосов
/ 11 октября 2019

Сканер не использует группы захвата как заменить все .

Вместо этого вы должны использовать отрицательный взгляд позади. Таким образом, ваш шаблон будет выглядеть следующим образом:

(?<!\\)@

Это также очищает требуемый класс отрицания.

Где : просто заменяется на <! Чтобы создать группу без захвата, посмотрите отрицательно на группу.

...