Привет, коллеги. Поговорим о магии, регулярных выражениях и учете/игнорировании регистра символов.
Как мы все знаем, в регулярном выражении есть символы, означающие сами себя, и есть спецсимволы, смысл которых иной. Слеш (\) превращает обычный символ в специальный и наоборот. Так, n означает букву n, но \n — это символ конца строки, тогда как \\ — это сам слеш.
Классикой регулярных выражений является использование точки как "любой символ", квадратных скобок для класса символов ([a-z] или [аоуеэи]), символов ^ и $ как якорей начала и конца строки, * как мультипликатора "нуль или более вхождений".
Это всё называется магией, вполне официально.
Но вы можете сами решать, сколько магии вам надо.
Дело в том, что есть развилка. В текстовом редакторе иногда не надо много магии: лучше, чтобы почти все символы означали сами себя, и можно было найти многоточие как /... А иногда нужно нормальное регулярное выражение, чтобы найти ^\s*[a-z]\+. А порой лучше, чтобы вообще всё, кроме букв и цифр, имело особый смысл. Например, чтобы + означал "один или более", как в Перле, а не знак "плюс".
Когда символ означает сам себя, говорят, что он трактуется литерально.
Можно указать в регулярном выражении (в любом месте) один из символов \v, \m, \M, \V. Первый, расшифровываемый как "very magic", трактует только буквы, цифры и знак _ литерально: всё остальное волшебно. Его антипод \V трактует всё литерально, кроме слеша и символа, который заканчивает регулярное выражение (/ или ?).
То есть, в обоих случаях вам всё доступно, только вопрос в удобстве: удобнее искать /\V...***...***[[[]]]/, но /\v(^\s*[a-z]+$)|(^\s+$)/
Если вы ищете просто текст, возможно, длинный, или, скажем, формулы, то \V незаменимо. А для сложных длинных выражений полезно \v.
Варианты \m и \M компромиссны. Первое соответствует обычным регулярным выражениям Вим и включено, если выставлен флаг magic (по умолчанию). Второе чуть менее волшебно и соответствует сброшенному флагу (nomagic). Сами эти последовательности позволяют флаг обойти. В режиме nomagic литеральна точка, звездочка, тильда; но волшебны крышечка и доллар. Квадратные скобки литеральны, а для класса символов достаточно экранировать только первую: \[a-z]. В режиме magic всё перечисленное волшебно, но вот +, |, круглые и фигурные скобки литеральны.
Основная разница: в режиме magic выражение ^.*$ означает "что угодно, строка целиком", а в режиме nomagic это "точка и звездочка и больше ничего на строке". В режиме \V это просто данный текст: "^.*$".
Итак, вы можете:
- Работать в парадигме Вим (при включенной magic). Это довольно разумный компромисс, но надо привыкнуть, что \w\+, а не \w+.
- Выставить nomagic и работать почти просто с текстом (только \, ^, $ означают не себя).
- Настраивать каждое выражение отдельно, задавая последовательность \v, \m, \M, \V.
Пример: "Строка состоит из двух одинаковых частей" выглядит так:
- /\v^(.+)\1$
- /\m^\(.\+\)\1$/ и это так без \m, если выставлена magic (по умолчанию).
- /\M^\(\.\+\)\1$/ и это так без \M, если выставлена nomagic.
- /\V\^\(\.\+\)\1\$/
Круглые скобки, волшебные или со слешем, захватывают текст. А символ \1 означает "то, что захватили первые по счету скобки".
Команды замены есть с заданной магией. Но о них будет отдельный материал.
Теперь про регистр символов. Рекомендую мой материал про регистр вообще и как его менять в Вим. А сегодня поговорим про его учет при поиске.
Поиск по регулярному выражению может учитывать регистр, а может игнорировать. Иногда нужно одно, иногда необходимо другое. Есть опция-флаг ignorecase: если включена, то поиск регистронезависим, и поиск любого слова из Francesca, francesca, FRANCESCA найдет любое из них. Если вы работаете на Фортране, включайте; если на С++, то отключайте. Если с текстом — смотрите по ситуации.
Есть еще smartcase, тоже флаг. Учитывается только при выставленном ignorecase, что логично. Если шаблон не содержит заглавных букв, то регистр игнорируется: francesca совпадет с любым из вариантов выше. А вот если заглавные буквы есть, то регистр учитывается, так что Francesca совпадет только с Francesca. Этот трюк не работает с *, # , gd и т.п.: только с /, ?, n, N, фильтрами :g, :v, заменой :s. Если вы ищете слово, то либо регистр учитывается, либо нет.
Можно в конкретном выражении включить или отключить учет регистра: для этого есть ключи \c и \C. Первое предписывает игнорировать регистр, второе предписывает учитывать, независимо от флагов, описанных выше.
Ещё есть ключ \Z, который предписывает игнорировать символы-модификаторы Юникода. Для русского языка это не очень важно, у нас с диакритикой только ё, Ё, й, Й (да и для них обычно используем цельные символы), а вот для языков с диакритикой это может быть полезно. А если вы работаете с огласованным ивритом или арабским, то это точно очень полезно!
В следующий раз обсудим поиск более детально. А потом замену, там свои нюансы.
До встречи, коллеги!