Найти в Дзене
Блокнот математика

Рубрика "Секреты Вим". Регулярные выражения. Якоря

Всем привет, продолжаем изучать регулярные выражения Вим! Сегодня поговорим о якорях — позициях в тексте.

Первая статья про регулярные выражения

Итак, якоря — это символы, совпадающие в определенных позициях строки, но имеющие нулевую длину (то есть это чисто позиции). Иногда их и называют "совпадения нулевой длины". Типичные примеры: начало строки, конец строки, граница слова, конец и начало совпадения, конец предыдущего совпадения.

Самые часто употребимые, пожалуй, якоря — это крышечка ^ и доллар $, совпадающие в начале и конце строки. Там, где этот смысл неуместен, они совпадают с собой, то есть утрачивают свою особость. Например, ^\d совпадает, если первым символом строки идет цифра, а ^\s*% — если первым непробельныи символом является процент, который начинает комментарий в ТеХе; так можно найти строки, в которых ничего нет, кроме комментария. А вот в выражении \d^ смысл "начало строки" у символа ^ бесполезен: такое выражение совпадать не может в принципе: ну как может быть, что сначала идут цифры, а потом начинается текст? Поэтому ^ означает просто ^.

Выражение ^\s*$ совпадает в визально пустой строке: в которой могут быть только пробельные символы. Обратите внимание, что ^$ означет пустую строку в строгом смысле, в которой нет ничего, в том числе и пробелов: в реальной работе с текстом полезнее первое выражение. Если опустить один из якорей, выражение совпадет всегда, в любой строке — это очень важно понимать! Потому что начало и конец строки есть у любой строки, и нуль или более пробелов тоже найдется в любой позиции.

Очень распространена замена s/^/!/ — поставить в начало строки символ комментария. Можно указать номера строк, например 42,666s/^/!/, или выбрать строки через V и потом сделать замену.

Далее идут границы слов: левая \< и правая \> В отличие от Перла, в котором граница (\b) не делится на лево- и правостороннюю, в Виме разница есть. Обратите внимание на набор словных символов, заданных в переменной iskeyword.

Вещь полезная, и поиск по слову (* и решетка, которые ищут слово под курсором вперед и назад, соответственно) ищут именно слово. То есть, если курсор на слове ion и вы нажмете *, то выражение поиска будет \<ion\>. Например, на словах function, ionic или championship оно не совпадет.

Символы \zs \и ze совпадают в любой позиции, и устанавливают начало и конец совпадения. Позволяют не включать в совпадение что-либо (до начала или после конца), то есть осуществлять проверку. Например,

: s/^\s*\zsif/

совпадет со словом if, перед котором идут только пробелы (но они в совпадение не войдут). Это полезно при замене, чтобы заменить только то, что нужно.

Например,

%s/double precision:: \zsbadname\ze/goodname/g

Заменится только имя, но не везде, а только в определении. Полезно. Хотя можно то же проделать и с захватом:

%s/\(double precision:: \)badname/\1goodname/g

Если \zs или \ze встречаются несколько раз, в силу вступает последний. Это удобно при повторном использовании когда-то придуманных выражений, а также при использовании квантификаторов:

\(.\{-}\zs666\)\{13}

найдет тринадцатое вхождение числа 666. Обратите внимание на ленивый квантификатор \{-}, забирающий как можно меньше символов.

Есть и опережающие и ретроспетивные проверки. Их четыре: и опережающая, и ретроспективная может быть позитивной и негативной. Опережающая позитивная \@= совпадает, если после данной позиции совпадает то, что указано (перед символом \@=). Негативная совпадает, если после позиции НЕ совпадает то, что указано. Ретроспективная действует аналогично назад от данной позиции. Например, целая часть числа — это цифры, но при условии, что после идет точка (или точки и цифры, тут уж зависит), причем точка частью целой части числа не является:

\d\+\.\@= или \d\+\(\.\d\+\)\@=

Важно, что это совпадения нулевой длины. Проверяется наличие текста после, но он не входит в совпадение. Поэтому если в выражении что-то ещё потом есть, оно должно совпасть с этим текстом, наличие которого уже проверено:

foo\(bar\)\@=not не совпадет никогда, потому что после foo должно идти bar, но в этой же позиции мы ищем not. Не найдем, там же bar.

Негативная проверка — это \@! после атома (символа или скобок). Например, end\(\s*if\)\@! совпадет на end, после которого не идет if.

Вот полезный пример: /^\%(.*bar\)\@!.*\zsfoo

Это строки, где есть foo, но нет bar. Сначала проверка убедится, что в строке нет bar, ни в одной позиции, а потом найдет foo.

Ретроспективные проверки проверяют наличие (отсутствие) совпадения до текущей позиции. В отличие от Перла, могут быть переменной длины. Позитивная проверка: \@<= после атома (символа или скобок). Пример:

-\@<=\d\+ — совпадет с отрицательным числом, но минус не входит.

Негативная проверка: \@<!

Отмечу, что проверки бывают полезны, но чаще всего удается обойтись якорями \zs, \ze.

Идем далее. Обычно в Вим поиск по выражению идет в пределах строки, но это не обязательно. Есть символ \n, который совпадает с концом строки, и можете искать хоть по всему тексту.

Символы \%^ и \%$ совпадают в начале и конце файла.

Это редко бывает нужно, на самом деле, но всяко бывает.

Теперь про чисто вимовские штуки, аналогов которых в Перле нет, потому что это специфика текстового редактора.

\%V совпадает, если позиция внутри выделенного текста. Текст выделяем с помощью v (от позиции до позиции), V (построчно) или C-V (прямоугольником). Это позволяет использовать замену не по всей строке, а в ее выделенной части. Или в выделенном прямоугольнике, например, в столбце таблицы. Бывает очень полезно, например, при редактировании текстовых карт.

\%# совпадает в позиции курсора, а \%'m, \%<'m, \%>'m — в позиции метки m, до нее и после нее.

\%42l — в строке 42, \%<42l — выше строки 42, \%>42 — ниже. Это позволяет искать текст там, где нужно, например — в теле функции. Для замены можно задать диапазон:

:42,666s/foo/bar/

а для поиска — только так: /\%>42lfoo\%<666l

Красным отмечены якоря, и значком якорька тоже. Синие — квантификаторы. Совпадет на фразах I love you и I love you not, если на строке больше ничего нет. Но совпадет еще много где — это должно быть ясно. Если совпадет, то совпадение будет только слово из 4 букв.
Красным отмечены якоря, и значком якорька тоже. Синие — квантификаторы. Совпадет на фразах I love you и I love you not, если на строке больше ничего нет. Но совпадет еще много где — это должно быть ясно. Если совпадет, то совпадение будет только слово из 4 букв.

Удачи!

Путеводитель по рубрике

Путеводитель по каналу

Наука
7 млн интересуются