РУКОВОДСТВО ПОЛЬЗОВАТЕЛЯ VIM - Брам Мооленаар

Шаблоны и команды поиска

В главе 3 мы рассматривали несколько простых примеров задания шаблонов для поиска (03.9). Vim может искать соответствия гораздо более сложным шаблонам. В этой главе показаны наиболее часто употребляемые элементы шаблонов. Более подробное описание шаблонов можно прочитать здесь: |шаблон|.

27.1    Поиск без учёта регистра
27.2    Продолжение поиска в конце файла
27.3    Смещения
27.4    Поиск соответствий для повторяющихся шаблонов
27.5    Варианты
27.6    Символьные диапазоны
27.7    Символьные классы
27.8    Соответствие для переноса строки
27.9    Примеры

Следующая глава: Складки
Предыдущая глава: Выполнение повторяющихся операций
Содержание: Руководство пользователя Vim


27.1 Поиск без учёта регистра

По умолчанию поиск в Vim зависим от регистра символов, использованных в шаблоне. "Include", "INCLUDE" и "include" воспринимаются как три разных слова и по простому шаблону будет найдено только одно из этих слов.

Опция 'ignorecase' позволяет включить регистронезависимый поиск:

:set ignorecase

Теперь, если вы повторите поиск для слова "include", то будут найдены также слова "Include", "INCLUDE" и "InClUDe". (Чтобы наглядно видеть на экране соответствия шаблону поиска, включите опцию 'hlsearch').

Выключить регистронезависимый поиск можно по команде:

:set noignorecase

Однако, оставим эту опцию включённой и попробуем поискать слово "INCLUDE". Соответствия шаблону останутся без изменений. Теперь, включим опцию 'smartcase':

:set ignorecase smartcase

Если в вашем шаблоне есть хотя бы один символ в верхнем регистре, то поиск будет регистрозависимым. Иными словами, если вам необходимо точное соответствие только слову с символами в верхнем регистре, то введите его в шаблоне так как оно есть, в противном случае просто набирайте шаблон строчными буквами. Разве не классно?

Вот что будет найдено с обеими включёнными опциями в зависимости от шаблона:

шаблон           соответствия ~
слово            слово, Слово, СЛОВО, СлОВо и т.д.
Слово            Слово
СЛОВО            СЛОВО
СлОВо            СлОВо
ИЗМЕНЕНИЕ ОТНОШЕНИЯ ПОИСКА К РЕГИСТРУ НА ОДИН РАЗ

Если вы желаете отменить регистрозависимый характер поиска для одного шаблона, то начните шаблон с символов "\c". Использование "\C", наоборот, сделает данный шаблон регистрозависимым. При использовании в шаблоне символов "\c" или "\C", значение опций 'ignorecase' и 'smartcase' не имеет значения.

шаблон           соответствия ~
\Cслово          слово
\CСлово          Слово
\cслово          слово, Слово, СЛОВО, СлОВо и т.д.
\cСлово          слово, Слово, СЛОВО, СлОВо и т.д.

Преимущество использования "\c" и "\C" состоит в том, что эти символы связаны с самим шаблоном, поэтому, независимо от текущих значений опций 'ignorecase' и 'smartcase', такой шаблон можно повторять из истории поиска с таким же результатом, как и до этого.

Замечание: Использование элементов, начинающихся с "\", в шаблонах поиска зависит от значения опции 'magic'. В данной главе подразумевается, что эта опция включена, поскольку это стандартное и рекомендованное значение опции. Если вы измените значение опции 'magic', то многие шаблоны поиска перестанут работать правильно.

Замечание: Если поиск выполняется дольше, чем ожидалось, то его можно прервать командой CTRL-C на Unix и CTRL-Break на MS-DOS и MS-Windows.


27.2 Продолжение поиска в конце файла

По умолчанию, поиск вперёд начинает поиск по шаблону с текущего положения курсора и продолжается до конца файла. Если требуемая строка не была найдена, то поиск затем продолжается уже в начале файла, пока таким образом не будет просмотрен весь файл, до текущего положения курсора.

Имейте в виду, что повторяя поиск по команде "n" вы рано или поздно вернётесь к первому найденному соответствию. Если вы этого не заметите, то можете нечаянно продолжать поиск до бесконечности. Vim предупредит вас о том, что происходит, сообщением:

поиск будет продолжен с НАЧАЛА документа ~

Если вы используете команду "?" для поиска в обратном направлении, то вы получите такое сообщение:

поиск будет продолжен с КОНЦА документа ~

Чтобы нагляднее видеть, где находится первое соответствие, включите линейку при помощи опции 'ruler':

:set ruler

Теперь Vim будет показывать позицию курсора в нижнем правом углу окна (или в строке состояния):

101,29       84% ~

Первое число это номер строки. Запомните его при первом совпадении, чтобы не пойти на второй круг при поиске.

ОТКЛЮЧЕНИЕ ПРОДОЛЖЕНИЯ ПОИСКА С ДРУГОГО КОНЦА ФАЙЛА

Чтобы отключить продолжение поиска с другого конца файла, воспользуйтесь командой:

:set nowrapscan

Теперь при достижении конца файла появится сообщение об ошибке:

E385: поиск закончен в КОНЦЕ документа; forever не найдено ~

В этом случае, чтобы найти все соответствия, можно перейти в начало файла по команде "gg" и вести поиск до появления такого сообщения об ошибке.

При поиске в обратном направлении по команде "?", в конце поиска появится сообщение:

E384: поиск закончен в НАЧАЛЕ документа; forever не найдено ~

27.3 Смещения

По умолчанию, команда поиска перемещает курсор в начало соответствия шаблону. При помощи смещения можно указать Vim  переместить курсор в какое-либо другое место. Для команды поиска вперёд ("/"), смещение указывается при помощи добавления косой черты (/) и величины смещения:

/default/2

Эта команда ищет соответствия шаблону "default" и перемещает курсор в начало второй строки после найденного соответствия. Применив эту команду в предыдущем абзаце, мы увидим, как Vim находит на первой строке слово "default" и затем перемещает курсор на две строки вниз, руководствуясь смещением.

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

СИМВОЛЬНЫЕ СМЕЩЕНИЯ

Смещение "e" указывает на смещение от конца соответствия. Команда:

/const/e

вызывает перемещение курсора к последнему символу соответствия, в данном случае к символу "t" в слове "const".

Путём добавления числа к смещению "e", можно задавать число символов, начиная от последнего символа совпадения, на которое следует переместить курсор. Например, команда

/const/e+1

перемещает курсор на один символ вправо от последнего символа соответствия шаблону const. Положительные числа перемещают курсор вправо, отрицательные влево:

/const/e-1

перемещает курсор к символу "s" в слове "const".

Если смещение начинается с символа "b", то курсор перемещается в начало совпадения. Это может показаться не столь полезным, поскольку отсутствие смещения "b" выполняет ту же самую операцию, но с "b" также можно указывать положительные или отрицательные значения. Например:

/const/b+2

перемещает курсор к началу соответствия и затем на два символа вправо. Таким образом, курсор оказывается на символе "n".

ПОВТОРЕНИЕ ПОИСКА С РАЗЛИЧНЫМИ СМЕЩЕНИЯМИ

Для повторения поиска по указанному раннее шаблону с новым смещением, не указывайте в новом поиске шаблон. Например:

/that
//e

что равноценно команде:

/that/e

Для повторения поиска со смещением, указанным раннее:

/

То же самое делает, кстати, и команда "n". Для повторения вместе с удалением раннее указанного смещения:

//
ПОИСК В ОБРАТНОМ НАПРАВЛЕНИИ

С командой поиска в обратном направлении "?" смещения используются аналогичным образом, но для отделения шаблона от смещения используется символ "?" вместо "/":

?const?e-2

Символы "b" и "e" сохраняют своё значение, а не меняют его на обратное, при использовании команды "?".

ИСХОДНАЯ ПОЗИЦИЯ ДЛЯ ПОИСКА

Обычно поиск начинается с позиции, в которой находится курсор. При указании числового смещения это может привести к проблемам. Например:

/const/-2

Эта команда поиска найдёт следующее слово "const" и переместит курсор на две строки вверх. Если вы воспользуетесь командой "n" для повторного поиска, то Vim может найти то же самое соответствие, что и раннее, и приведёт вас обратно в ту же самую позицию!

Но всё может быть даже хуже: Предположим, что на следующей строке есть другое слово "const". В таком случае, это соответствие будет обнаружено, и курсор будет перемещён ещё дальше назад по тексту.

При указании символьного смещения Vim помнит об этом, так что при повторном поиске позиция курсора будет соответствующим образом скомпенсирована, чтобы то же самое соответствие больше не стояло на пути команды поиска.


27.4 Поиск соответствий для повторяющихся шаблонов

"*" в шаблоне поиска указывает на то, что предшествующий ей элемент шаблона может повторяться любое количество раз. Например:

/a*

обнаружит соответствия "a", "aa", "aaa" и т.д. Но в том числе, будет также обнаружена и пустая строка "", поскольку нулевое число совпадений также будет считаться соответствием шаблону.

"*" применяется только к элементу, который стоит непосредственно перед звёздочкой. "ab*" будет соответствовать "a", "ab", "abb", "abbb" и т.д. Чтобы найти соответствие повторяющейся строке, она должна быть представлена как один элемент шаблона. Это можно сделать, поместив шаблон внутри пар символов "\(" и "\)". Таким образом, команда

/\(ab\)*

найдёт следующие соответствия: "ab", "abab", "ababab" и т.д, а также "".

Чтобы избежать появлению пустой строки среди соответствий шаблону поиска, используйте "\+". Этот символ указывает на то, что предшествующий элемент шаблона может повторяться один и более раз.

/ab\+

будет соответствовать "ab", "abb", "abbb" и т.д., но не будет соответствовать "a" без последующего "b".

Для указания на возможный элемент шаблона, используйте "\=". Например:

/folders\=

будет соответствовать как "folder", так и "folders".

ТОЧНОЕ УКАЗАНИЕ КОЛИЧЕСТВА ПОВТОРЕНИЙ ЭЛЕМЕНТА ШАБЛОНА

Чтобы указать точное значение повторений элемента шаблона, используйте форму "\{n,m}". Здесь "n" и "m" это числа. При поиске, предшествующий элемент должен повторяться от "n" до "m" раз |включительно|. Пример:

/ab\{3,5}

будет соответствовать "abbb", "abbbb" и "abbbbb".

Если "n" опущено, то по умолчанию оно принимается равным нулю. Если опущено "m", то по умолчанию оно принимается равным бесконечности. Если опущено ",m", то по умолчанию оно принимается равным "n". Примеры:

Шаблон Возможное количество повторений
\{,4} 0, 1, 2, 3 или 4
\{3,} 3, 4, 5 и т.д.
\{0,1} 0 или 1, то же, что и \=
\{0,} 0 и более, то же, что и *
\{1,} 1 и более, то же, что и \+
\{3} 3
ПОИСК МИНИМАЛЬНОГО СООТВЕТСТВИЯ

Предыдущие примеры включали в соответствие как можно больше символов. Чтобы находить минимальное количество соответствующих символов, используйте форму "\{-n,m}". Она работает точно так же, как и "\{n,m}", за исключением того, что в соответствие будет включено минимальное количество повторяющихся элементов.

Например:

/ab\{-1,3}

будет соответствовать "ab" в "abbb". В действительности, это соответствие никогда не будет находить более одного символа b, поскольку в этом нет никакой необходимости. Чтобы отмечать больше, чем указано в минимальном ограничении, требуется какое-либо еще влияние в шаблоне.

При отсутствии "n" и "m" применяются те же самые правила. Более того, можно убрать оба значения, оставляя в шаблоне лишь "\{-}". Такой шаблон будет находить предшествующий элемент минимальное количество раз от нуля до бесконечности. Сам по себе элемент всегда будет указывать на нулевое количество повторений. Но посмотрите, что если такая конструкция используется совместно с чем-то еще:

/a.\{-}b

Такой шаблон найдёт соответствие "axb" в "axbxb". Если бы использовался шаблон

/a.*b

то было бы найдено максимально возможное количество символов, то есть соответствием было бы целое "axbxb".


27.5 Варианты

Оператором "или" в шаблоне служит "\|". Пример:

/foo\|bar

Такой шаблон соответствует как "foo", так и "bar". Можно использовать и несколько вариантов:

/один\|два\|три

Соответствует любому из слов "один", "два" и "три".

Чтобы соответствие варианту в шаблоне могло повторяться один и более раз, возьмите определение вариантов в скобки "\(" и "\)":

/\(foo\|bar\)\+

Это будет соответствовать "foo", "foobar", "foofoo", "barfoobar" и т.д.

Другой пример:

/end\(if\|while\|for\)

соответствует любому из слов "endif", "endwhile" или "endfor".

Похожий по смыслу действия оператор в шаблоне -- "\&". Он требует, чтобы оба варианта совпадали в одном и том-же найденном соответствии. Само соответствие при этом использует последний указанный вариант. Например:

/forever\&...

Соответствует "for" в "forever", но не в "fortuin".


27.6 Символьные диапазоны

Для соответствия "a", "b" или "c" вы можете использовать форму "/a\|b\|c". Однако, чтобы задать шаблон для соответствия любой букве от "a" до "z", потребуется ввести слишком длинный шаблон с вариантами. Вот более краткий способ:

/[a-z]

Конструкция [] задаёт соответствие для одного символа. Внутри квадратных скобок указываются различные варианты символов, которые могут быть использованы, например:

/[0123456789abcdef]

определяет соответствие шестнадцатеричной цифре. Для символов, находящихся рядом в таблице, можно также задавать символьный диапазон. "0-3" можно подставить вместо "0123", "w-z" вместо "wxyz". Таким образом, предыдущая команда может быть сокращена до:

/[0-9a-f]

Для включения в список символьных вариантов символа "-", укажите его в самом начале или конце списка. Кроме того, можно использовать такие специальные символы (их можно использовать в любом месте шаблона, на только в []):

\e <Esc>                                  
\t <Tab>
\r <CR>
\b <BS>

Имеется также несколько дополнительных возможностей для использования внутри диапазонов [], см. |/[]|.

ДИАПАЗОН С ИСКЛЮЧЕНИЕМ

Для того, чтобы исключить какой-либо символ из диапазона, используйте в начале диапазона символ "^". В этом случае диапазон будет соответствовать любому символу, кроме указанных в диапазоне []. Пример:

/"[^"]*"  
 " Двойная кавычка
  [^"] любой символ, кроме двойной кавычки
      * любое количество раз
       " еще раз двойная кавычка

соответствует "foo" и "3!x", включая двойные кавычки.

СТАНДАРТНЫЕ ДИАПАЗОНЫ

Некоторые диапазоны используются в работе постоянно. Для таких диапазонов в Vim имеются короткие обозначения. Например:

/\a

будет находить алфавитные символы. Это эквивалентно использованию "/[a-zA-Z]". Вот еще несколько примеров:

элемент соответствие эквивалент
\d цифра [0-9]
\D не цифра [^0-9]
\x шестнадцатеричная цифра [0-9a-fA-F]
\X не шестнадцатиричная цифра [^0-9a-fA-F]
\s пробел [     ]     (<Space> и <Tab>)
\S не пробел [^     ]     (не <Space> и <Tab>)
\l буква в нижнем регистре [a-z]
\L не буква нижнем регистра [^a-z]
\u буква в верхнем регистре [A-Z]
\U не буква верхнем регистра [^A-Z]

Замечание: Использование стандартных диапазонов позволяет осуществлять поиск значительно быстрее, чем с использованием их эквивалентов. Стандартные диапазоны не могут использоваться внутри []. Поэтому, "[\d\l]" не будет соответствовать цифре или букве в нижнем регистре. Вместо этого, используйте форму "\(\d\|\l\)".

Полный список стандартных диапазонов см. в |/\s|.


27.7 Символьные классы

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

Например, попробуйте поиск по такому шаблону:

/\f\+

"\f" обозначает символы, которые могут входить в имена файлов. Таким образом, шаблон соответствует строке, которая может быть именем файла.    Набор символов, которые могут входить в имя файла, зависит от операционной системы. На MS-Windows этот набор включает обратную косую черту, а на Unix - нет. Список символов определяется опцией 'isfname'. Значение этой опции по умолчанию для Unix следующее:

:set isfname
isfname=@,48-57,/,.,-,_,+,,,#,$,%,~,=

Для других систем значение по умолчанию отличается. Поэтому, можно пользоваться шаблоном с "\f" для поиска имени файла, и он автоматически будет подстраиваться под вашу операционную систему.

Замечание: В действительности, Unix позволяет использовать в имени файла практически любой символ, включая пробел. Поэтому, теоретически, включение этих символов в опцию 'isfname' было бы правильным, но это сделало бы невозможным определение конца имени файла в тексте. Поэтому принято указанное выше компромиссное значение этой опции.

Другие символьные классы:

элемент соответствие опция
\i символы имён 'isident'
\I как \i, исключая цифры  
\k символы ключевых слов 'iskeyword'
\K как \k, исключая цифры  
\p печатные символы 'isprint'
\P как \p, исключая цифры  
\f символы имён файлов 'isfname'
\F как \f, исключая цифры  

 


 

27.8 Соответствие для переноса строки

Vim может осуществлять поиск по шаблону, включающему перенос строки. Для этого вам необходимо указать, где происходит перенос строки.

Чтобы указать на перенос строки в определённом месте шаблона, используйте элемент "\n":

/это\nслово

будет соответствовать слову "это" в конце строки, если следующая строка начинается со слова "слово". Чтобы также искать соответствия строке "это слово", шаблон должен быть составлен так, чтобы соответствовать пробелу или переносу строки. Это достигается с использованием элемента "\_s":

/это\_sслово

Чтобы шаблон мог соответствовать любому количеству пробельных символов, используйте

/это\_s\+слово

Такой шаблон также будет соответствовать и такой ситуации: "это   " в конце одной строки и "   слово" в начале другой.

"\s" соответствует пробелу, а "\_s" соответствует пробелу или переносу строки. Аналогично, "\a" соответствует символу латинского алфавита, а "\_a" соответствует символу латинского алфавита или переносу строки. При помощи "_" можно изменить подобным образом и другие символьные классы и диапазоны.

Для соответствия переносу строки можно также доработать при помощи "\_" и многие другие элементы. Например, "\_." соответствует любому символу или переносу строки.

Замечание: "\_.*" соответствует всем символам до конца файла. Будьте осторожны с использованием этого шаблона, поскольку поиск по нему может быть очень медленным.

Другой пример: "\_[]", символьный диапазон, включающий перенос строки.

/"\_[^"]*"

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


27.9 Примеры

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

ПОИСК АВТОМОБИЛЬНЫХ НОМЕРНЫХ ЗНАКОВ ШТАТА КАЛИФОРНИЯ

Номерные знаки в Калифорнии выглядят так: "1MGU103". Он включает цифру, три символа в верхнем регистре и три цифры. Иными словами, говоря на языке шаблонов:

/\d\u\u\u\d\d\d

Другой способ задания шаблона заключается в применении числа повторений:

/\d\u\{3}\d\{3}

Можно также использовать диапазоны []:

/[0-9][A-Z]\{3}[0-9]\{3}

Так каким же шаблоном пользоваться лучше всего? А любым, который вы можете легко запомнить, чем проще, тем лучше. Если вы без труда запоминаете все три варианта, то лучше всё-таки воздержаться от использования третьего, поскольку он требует слишком много лишних нажатий на кнопки и более медленный в работе.

ПОИСК ИМЕНИ

В программах на языке C, да и многих других языках программирования, имя начинается с буквы и состоит в дальнейшем из букв и цифр. Также может использоваться символ подчёркивания. Шаблон для поиска имени выглядит так:

/\<\h\w*\>

"\<" и "\>" используются для нахождения целых слов. "\h" эквивалентно "[A-Za-z_]", а "\w" это то же самое, что и "[0-9A-Za-z_]".

Замечание: "\<" и "\>" полагаются на значение опции 'iskeyword'. Если она включает, например, "-", то "ident-" не будет найден. В этой ситуации пользуйтесь шаблоном: /\w\@<!\h\w*\w\@! который проверяет соответствие "\w" перед именем и после имени. См. |/\@<!| и |/\@!|.


Следующая глава: Складки
Авторские права: см. Авторские права