Regex: повторяющиеся совпадения с использованием начала строки

Скажем, я хотел бы заменить все a, которые находятся после двух начальных a, и у которых есть только a между ними и первыми двумя a. Я могу сделать это в Vim, используя (очень волшебное \v) регулярное выражение s:\v(^a{2}a{-})@<=a:X:g:

aaaaaaaaaaa

идет к

aaXXXXXXXXX

Однако почему s:\v^a{2}a{-}\zsa:X:g заменяет только первое вхождение? то есть, давая

aaXaaaaaaaa

Я предполагаю, что это связано с тем, что первое совпадение «поглощает» начало строки и первые 2 a, так что последующие совпадения совпадают только с тем, что осталось от строки, которая никогда не может снова соответствовать ^. Это правда? Или, вернее, каково наиболее педагогическое объяснение?

P.S. Это минимальный пример другой проблемы.

Редактировать

Принятый ответ исправил опечатку в исходном регулярном выражении (отсутствует ^), а его комментарий ответил на вопрос: почему ^ можно «повторно использовать» в ретроспективном выражении, но не в случае \zs? (Ответ: просмотр назад не использует совпадение, а \zs использует.)

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
22
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Дело в том, что (a{2}a{-})@<=a соответствует любому a (см. последний a), которому предшествуют два или более символов a. В разновидностях регулярных выражений NFA он равен (?<=a{2,}?)a, см. его демонстрация.

Регулярное выражение ^a{2}a{-}\zsa соответствует началу строки, затем двум или более a, затем отбрасывает этот совпадающий текст и соответствует a. Таким образом, он не может сопоставляться с другими a, поскольку ^ привязывает совпадение к началу строки (и не допускает сопоставления где-либо еще).

Вы, вероятно, захотите продолжить использовать конструкцию просмотра назад и добавить туда ^ (если вы хотите начать сопоставление только в том случае, если строка начинается с двух a):

:%s/\v(^a{2}a{-})@<=a/X/g

Абсолютно, это то, что я имел в виду! Это была моя некрасивая опечатка! Исправлено сейчас. Вопрос больше в том, «почему ^ можно повторно использовать в ретроспективном просмотре, но не в случае \zs

Stalpotaten 17.03.2022 17:32

@Stalpotaten Потому что шаблон просмотра назад не потребляет много энергии. \zs отмечает только начало значения совпадения после потребление части слева.

Wiktor Stribiżew 17.03.2022 17:45

Другие вопросы по теме