Захват групп в регулярных выражениях - PullRequest
2 голосов
/ 19 июня 2019

У меня есть строка a/b/c/, и я хочу получить 3 группы (a/, b/, c/) по регулярному выражению.

Итак, я могу сделать это

^([^\/]+\/)([^\/]+\/)([^\/]+\/)$

но это не очень элегантно.Я хочу сделать что-то вроде этого

^([^\/]+\/){3}$

, но получаю предупреждение:

A repeated capturing group will only capture the last iteration. Put a capturing group around the repeated group to capture all iterations or use a non-capturing group instead if you're not interested in the data

Итак, меня интересуют данные, но я не понимаю, что мне следует изменитьв регулярном выражении, чтобы получить действительный результат.

Тест по регулярному выражению regex101

Небольшой пример для контекста (конфигурация nginx):

location ~* ^/([^/]+/)([^/]+/)([^/]+/)$ {
  rewrite (?i)^/([^/]+/)([^/]+/)([^/]+/)$ /$3$2$1 break;
}

в этом случаеЯ переписываю URL с /a/b/c/ на /c/b/a/.

Ответы [ 2 ]

0 голосов
/ 19 июня 2019

Шаблон ^([^\/]+\/){3}$ повторяет группу 3 раза, но группа 1 будет содержать только значение последней итерации.Возможно, эта страница на Возвращаемое значение для данной группы является последней полученной , может быть полезным.

Если вам нужны группы 1, 2 и 3, вы должны использовать 3 группы захвата в шаблоне.

Не уверен, что это считается более элегантным, но, возможно, это вариант для получения 3 отдельныхсовпадения, использующие \G для получения итеративных совпадений и положительный прогноз (?=, чтобы утверждать, что шаблон без косой черты, за которым следует /, встречается 3 раза:

(?:(?=^(?:[^/]+/){3}$)|\G(?!^))[^/]+/
  • (?: Группа без захвата
    • (?= Позитивный прогноз, утверждаем, что справа -
      • ^(?:[^/]+/){3}$ Совпадение 3 раза, не косая черта, затем /
    • ) Закрыть позитивный прогноз
    • | Или
    • \G(?!^) Утверждать позицию в конце предыдущего матча, а не в начале
  • ) Закрыть группу без захвата
  • [^/]+/ Совпадает не с косой чертой, затем /

См. Регулярное выражение демо

0 голосов
/ 19 июня 2019

На самом деле вы мало что можете сделать, чтобы уменьшить дублирование:

^([^\/]+\/)([^\/]+\/)([^\/]+\/)$

Предупреждение говорит вам, что повторяющаяся группа, такая как ([^\/]+\/){3}, будет захватывать только последний повтор.Вы можете подумать, что ([^\/]+\/){3} - это 3 группы, но это только одна группа, потому что есть только одна пара скобок.Эта группа будет содержать последнее, что соответствует квантификатору, в данном случае c/.

Таким образом, чтобы иметь 3 группы, необходимо иметь 3 пары скобок.

Если вы действительно хотите сделать регулярное выражение короче, вы можете попробовать:

[^\/]+\/

Это создаст 3 совпадений вместо групп, но вам придется проверить, используя код,что:

  • существует ровно три совпадения
  • конец каждого совпадения является началом следующего совпадения
  • первый совпадение начинается в начале строки
  • последний матч заканчивается в конце строки

, чтобы достичь того же эффекта, что и исходное регулярное выражение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...