Предотвратите не жадную часть от потребления следующей дополнительной части - PullRequest
0 голосов
/ 14 ноября 2018

У меня есть регулярное выражение с обязательной частью, нежадной (ленивой?) Частью, необязательной частью и, наконец, еще одной не жадной частью.

<mandatory><non-greedy><optional><non-greedy>
Реализовано как:
^mandatory.*?(:?optionalpart)?.*?$

Необязательная часть состоит из «части, которую нужно найти» и «части, которую нужно вернуть в группу захвата».

^mandatory.*?(:?findme(matchme))?.*?$

Но для некоторых входных данных первая не жадная часть потребляет символы, которым должна соответствовать следующая дополнительная часть. Есть ли способ сделать опциональную часть более жадной, чем предыдущая, не жадная часть?


Пример: найти символ после 2, или найти пустую строку, если 2, отсутствует, но обязательная часть соответствует.

"Foo: 2,b,1,a,3,c" -> match, $1 = "b"
"Foo: 1,a,2,b,3,c" -> match, $1 = "b"
"Foo: 1,a,3,c,2,b" -> match, $1 = "b"
"Foo: 2,b"         -> match, $1 = "b"
"Foo: 1,a,3,c"     -> match, $1 = ""
"Fuu: 1,a,2,b,3,c" -> no match.

Попытка 1: ^Foo: .*?(?:2,([a-z]))?.*?$
Это терпит неудачу на 2-м и 3-м примере, возвращая "" вместо "2".

Попытка 2: ^Foo: .*?(?:2,([a-z])).*?$
Это исправляет предыдущие ошибки, но теперь в 5-м примере происходит сбой, не соответствует.
Часть, которая должна быть дополнительной, больше не является дополнительной.

Если это имеет значение, я использую класс Pattern Java.

-

Об этом спрашивали до , но ни для одного из нас не было удовлетворительного ответа.

1 Ответ

0 голосов
/ 14 ноября 2018

Ваше первое регулярное выражение очень близко, вам нужно переместиться (?: немного больше влево, чтобы включить шаблон .*?:

^Foo:(?: .*?2,([a-z]))?.*$
     ^^^ 

См. Демоверсию regex

Подробнее

  • ^ - начало строки
  • Foo: - некоторый буквальный текст
  • (?: .*?2,([a-z]))? - необязательная группа без захвата, которая соответствует жадно (будет пробоваться хотя бы один раз) 1 или 0 вхождений:
    • .*? - пробел, за которым следуют любые 0+ символов, кроме символов разрыва строки, как можно меньше
    • 2, - буквальная подстрока
    • ([a-z]) - Группа 1: строчная буква
  • .* - любые 0+ символов, кроме символов разрыва строки (остальная часть строки)
  • $ - конец строки.

Общая схема будет выглядеть так:

^<MANADATORY_LITERAL>(?:<NON_GREEDY_DOT>(<OPTIONAL_PART>))?<GREEDY_DOT>$
...