Волшебные замены в Vim, много файлов

3 ноября 2014. Комментарии .

Хотим сделать замену, описываемую регулярным выражением, в большом количестве файлов сразу. Рассмотрим эту процедуру на примере добавления тэга в нескольких html-файлах (знать html не надо).

Допустим, решили вставить во все файлы tag <meta> такого вида:

1
<meta http-equiv="refresh" content="seconds; URL-redirect-to">

Это один из способов (плохой) для включения переадресации с адреса oldsite.ru/page_name на newsite.ru/page_name и с oldsite.ru/folder/page_name на newsite.ru/folder/page_name для каждой страницы. Иными словами, мы хотим, чтобы в каждом файле появилось некоторое выражение, зависящее от имени файла.

Заходим в директорию с нашими html-файлами. Запускаем vim и выполняем:

Рекурсивное открытие файлов из всех поддиректорий
1
:args **/*html

Командой :ls убедитесь, что открыты все необходимые страницы. Теперь нужно решить, что будем менять. Перенаправляющий мета-tag надо поместить между <head> и </head>, поэтому неплохой идеей будет замена

1
<head>

на

1
2
<head>
<meta http-equiv="refresh" content="2; http://newsite.ru/page_name">

Для этого скопируем выражение выше в регистр, скажем, r (выделить + "ry). Уточняю: можно использовать именно page_name. Это просто шаблон, можно изменить его на что угодно, что не встречается на ваших страницах. Затем:

Меняем <head> на содержимое регистра r.
1
:argdo %s/<head>/\=@r/ge | update

В результате этой замены во всех файлах появится строка, содержащая шаблон page_name, который мы следующим действием заменим на реальное название файла. Содержимое регистра r вставляется выражением \=@r. Без команды «| update» vim не станет менять больше одного файла. Командой :ls можно проверить, в каких файлах изменение произошло, а в каких — нет: «line 0» говорит о том, что курсор в файле не перемещался, т.е. замен не происходило. Теперь меняем page_name на настоящее имя файла (регистр % хранит имя файла):

Регистр % всегда содержит имя файла.
1
:argdo %s/page_name/\=@%/ge | update

Вот, собственно, и всё. Тогда в файле abrikos.html, лежащем в корне, вместо <head> появится:

1
2
<head>
<meta http-equiv="refresh" content="2; http://newsite.ru/abrikos.html">

А в файле honduras.html из поддиректории countries вместо <head> появится:

1
2
<head>
<meta http-equiv="refresh" content="2; http://newsite.ru/countries/honduras.html">

В заключение мне хочется сказать, что те два года, что я общаюсь с редактором vim, меня не покидает ощущение волшебства. Я понял, что vim стал мне на самом деле удобнее любого другого редактора, когда стал угадывать его команды. Например, я знал, что удалить одно слово вместе с пробелом можно командой d a w. Как-то раз мне захотелось удалить предложение, и вспомнив, что по-английски предложение будет sentence, я нажал d a s — и это сработало. Однажды в чьём-то блоге (ссылку позабыл, к сожалению) я прочитал такое сравнение, воспроизвожу по памяти:

Конечно, нельзя сесть за vim и сразу начать работать. Необходимо приложить усилия, чтобы эффективно пользоваться мощнейшим текстовым редактором на свете. Многих это отпугивает. «Зачем», — говорят они, — «я буду тратить время на обучение, если и так могу отредактировать файл в своём любимом gedit, notepad++, geany?» Но ведь мало кого останавливает то, что машину нужно учиться водить. Зачем, мол, мне машина, если я могу ходить пешком и этому учиться не надо? Так и с vim. Вы тратите время на обучение, но затем работаете гораздо эффективнее. Вы учитесь водить машину, но затем перемещаетесь гораздо быстрее, чем пешком.

Красивое сравнение. Но неправильное. Освоить vim гораздо сложнее, чем научиться водить машину.