Вот что я получаю из документации: \zs
«запускает выделенную часть» после сопоставления с предыдущим регулярным выражением и \@<=
«запускает выделенную часть» после сопоставления с предыдущим атомом . Но я не совсем понимаю тонкости этого, так кто-нибудь может объяснить, как они отличаются немного глубже?
Это то, что заставило меня любопытно: если я бегу
/\_s\zsnnoremap
т. е. выберите nnoremap
предваряющий пробел или начало строки (т. е. новую строку из предыдущей строки, следовательно, \_
предшествующей s
) и затем запустите, gn
чтобы войти в визуальный режим и визуально выбрать следующее совпадение, по какой-то причине только первый столбец (т. е. выбрано первое n
в nnoremap
) - несмотря на то, что все nnoremap
слово выделено при :hlsearch
включенном.
Тем не менее, если я вместо этого запустить поиск
/\_s\@<=nnoremap
а затем попробуйте gn
, все nnoremap
правильно выбрано. Что здесь может происходить? Я (смею сказать) обнаружил какую-то неясную ошибку?
источник
:h patterns
но моя память предполагает, что регулярные выражения состоят из атомов, если это помогает объяснить разницу.Ответы:
Похоже, вы действительно нашли неясную ошибку. Я реализовал
gn
textobject еще в 2012 году для Vim 7.3. В основном это работает следующим образом:1) Он ищет в обратном порядке последнее совпадение текущего регулярного выражения.
2) Ищет следующее совпадение текущего регулярного выражения.
Это должно прояснить, что курсор будет в начале следующего матча, даже если он уже был в начале 1).
в заключение3) он ищет конец текущего регулярного выражения. и помещает курсор туда.Теперь то, что происходит здесь, заключается в том, что поиск конца текущего совпадения завершается и возвращается к концу предыдущего совпадения (потому что
wrapscan
оно уже установлено, после того как отключено для 1)). Затем он устанавливает визуальный маркер в область от начала (конца точки 2) и область, в которую перемещается следующий элемент поиска 3).Я более подробно рассмотрю проблему и, возможно, позже отправлю патч для Vim.
[Обновление 22.05.2018] Я написал и отправил патч, чтобы исправить это поведение.
[Update2 22.05.2018] И патч был объединен как патч уровня 8.1.0018
[Обновление 22.10.2019] Начиная с патча Vim 8.1.629, третий шаг больше не выполняется. Вместо этого Vim теперь может определять конец матча, когда находит начало матча (шаг 2).
источник
Кристиан полностью рассмотрел вопрос о багги поведения
gn
, но все еще есть существенные различия между\zs
и\@<=
. Самое большое существо\@<=
модифицирует предшествующий атом, в то время\zs
как это атом в самом себе.Рассматривать:
Соответствует регулярное выражение 1, так как
\%1c
соответствует столбцу 1 и там есть X.\zs
просто вызывает перезапуск матча с позиции после X.Регулярное выражение 2, однако, не соответствует, потому что, хотя
\%1c
соответствует первому столбцу,X\@<=
имеет нулевую ширину (как упомянуто в документации) иnnoremap
начинается со столбца 2. Ничто не может компенсировать разницу в положении между столбцами 1 и 2.Регулярное выражение 3 совпадает, так как
nnoremap
начинается в столбце 2.источник
nnoremap
из регулярных выражений будет производить спичку; но регулярное выражение до сих пор не удается даже без него . Я думаю , что он не потому , что\%1cX\@<=
выражает позицию , которая не может существовать.\%1c
соответствует положению в колонке 1, иX\@<=
просит характер ,X
чтобы соответствовать до этого. Но не может быть никакого символа перед первым столбцом. Именно поэтому, даже если заменитьX
с точкой (любой символ), регулярное выражение до\%1c.\@<=
сих пор не удается.\zs
применяется ко всему регулярному выражению и устанавливает следующий символ как первый символ всего совпадения. Все, что до\zs
, не будет включено как часть соответствующего текста.\@<=
, С другой стороны, влияет только на атомы непосредственно вокруг него, что позволяет указать, что следующий атом будет соответствовать только если он следует за предыдущий атом. Так, например, регулярное выражение:Будет сопоставлять весь текст между двумя экземплярами
bar
(включая сами экземпляры), но только если перед вторым предшествуетfoo
. то есть будет соответствовать:но нет:
Поскольку
\@<=
локализована таким образом, вы можете даже использовать\@<=
несколько раз в одном выражении:Ниже будет соответствовать три экземпляра
bar
, но только тогда , когда второй два, каждый предшествуетfoo
.т.е. с учетом текста:
Это будет соответствовать только первой строке.
источник
\zs
, то есть, это также должно работать:\vfoo\zsbar.*(foo)@<=bar
.\zs
которые вообще нельзя заменить.\zs
и\ze
может быть заменено взглянуть на шаблоны регулярных выражений, и они более мощные, верно? Более мощные причины, они могут использоваться более одного раза и могут быть сгруппированы\(\)
. А также потому, что они работают, как Perl, глядя вокруг регулярных выражений. Что-нибудь не так?\zs
/,\ze
когда вы можете, потому что они быстрее, чем осмотры.\zs
и\ze
, очевидно , более интуитивным. Спасибо за объяснения.