Лисаков и макромир

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

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

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

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

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

Существует много способов сделать перенаправление с адреса oldsite.ru/page_name на newsite.ru/page_name для каждой страницы. Наверняка большинство сделало бы такую операцию в perl или python. А я расскажу вам о самом волшебном способе: мы сделаем это в vim. Если Вы не знаете, что это такое, срочно покиньте эту страницу.

Расслабьтесь, сядьте поудобнее. Приготовьте свою волшебную палочку.
На медленном огне.

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

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

Обратите внимание, насколько крута команда :args — встроенный подсвечиватель кода её даже не знает!

Командой :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

Без команды «| update» vi не станет менять больше одного файла. Командой :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 стал мне на самом деле удобнее любого другого редактора, когда стал угадывать его команды. Например, я знал, что удалить одно слово вместе с пробелом можно командой daw. Как-то раз мне захотелось удалить предложение, и вспомнив, что по-аглицки предложение называют sentence, я просто нажал das — и это сработало.

Где-то однажды я прочитал такое красивое сравнение, воспроизвожу по памяти:

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

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