VIM

индекс
158,91

Vim. Одновременное изменение нескольких файлов. Развернутый пример с комментариями

Бывают ситуации когда нужно выполнить какую-то последовательность действий одновременно в нескольких файлах. Конечно, для этого можно использовать разные инструменты (навскидку: bash + sed/awk, python/perl, ...) — какие-то будут менее приспособлены для выполнения поставленной задачи, какие-то — более. Сейчас мы рассмотрим пример решения одной такой простой задачи средствами редактора Vim.

Рассмотрим простой пример: вставка строки в начало каждого файла.

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

Итак, приступим:

1. Открываем в редакторе все файлы в которых нужно сделать изменения:

$ vim -o file1.txt file2.txt file3.txt

Опция -o дает возможность открыть каждый файл в отдельном окне. Запуск с данной опцией в примере сделан не только для наглядности (все изменения будут видны сразу), но и исходя из еще одного момента о котором будет сказано ниже.

2. Записываем последовательность действий которую необходимо проделать над файлами в макрос:

qm1GOПервая строка<ESC>qu

qm — начало записи макроса в регистр m
1G — переход на первую строку файла
O (большая латинская буква O) — вставка строки перед текущей строкой с переходом в режим редактирования
Первая строка — содержание первой строки
<ESC> — выход из режима редактирования
q — окончание записи макроса
u — отмена изменений в текущем окне во избежания дублирования сделанных изменений

3. Запуск макроса m во всех окнах:

:windo normal @m

windo — команда запуска команды vim во всех окнах
normal — команда запуска команды нормального режима vim из командной строки, то есть две команды запуска макроса эквиваленты:
@m
:normal @m

Если бы мы просто сделали так:
:windo @m
то мы бы получили сообщение об ошибке «Это не команда редактора»
по сути мы бы в каждом окне выполнили такое действие:
:@m
что является неверным, поскольку мы запускаем команду нормального режима в командной строке. В итоге мы можем получить либо сообщение об ошибке либо непредсказуемые действия редактора.

Есть команды, аналогичные :windo:
:argdo
:tabdo
:bufdo

Первая команда — :argdo. Мощная команда, которая позволяет выполнить команду в списке файлов заданном как именованный аргумент. Здесь мы ее рассматривать не будем.
Вторая команда — :tabdo. Полностью аналогична нашей windo, но проделывает всю работы над всеми открытыми вкладками. Тут есть один момент о котором стоит упомянуть: в каждой вкладке может быть несколько окон. Так вот, изменения будут только в текущем окне каждой вкладки!
Ну инаконец третья команда — :bufdo. Выполняет команду над всеми буферами. Но при ее использовании есть один нюанс. Сама команда bufdo выполнится только в текущем буфере и завершится с ошибкой если «полезная» команда (та, которую запускает bufdo и которая должна выполниться в каждом буфере) изменяет текст.

Например так:
:bufdo normal G
выполнится нормально во всех буферах
а вот так так:
:bufdo normal GoEnd file
уже завершится с ошибкой. Что бы все заработало надо сделать так:
:bufdo! normal GoEnd file

Собственно это все на сегодня. За мой первый пост на хабре ногами прошу не пинать. Исправления, дополнения, замечания — приветствуются.
+34
31 августа 2009, 18:17
29

комментарии (13)

0
dmodeus #
C VIM даже рутинная работа превращается в развлечение :) Правда я его пока не осилил, но все больше убеждаюсь, что мощный редактор.
0
ryukzak #
Даже рутинная работа превращается в интересный квест с необходимостью повышенного внимания (режимы).
+1
elve #
А я начал знакомство с Linux с освоения vim. Редактор невероятно удобный, когда привыкнешь, но неинтуитивный интерфейс многих отпугивает ).

Про работу одновременно в нескольких вкладках даже не подозревал (хотя может оно мне не так сильно и нужно было...), так что автору респект!
0
chegivara #
А я постоянно пользуюсь табами.
Выставляю горячую клавишу <Сtrl> O на открытие нового таба:
0
chegivara #
А я постоянно пользуюсь табами(:tabnew).
Выставляю горячую клавишу <Сtrl> O на открытие нового таба:
nmap <C-o> :tabnew
И для открытия нового таба использую функцию:
:set tabline=%!ShortTabLine()

function ShortTabLine()
let ret = ''
for i in range(tabpagenr('$'))
" select the color group for highlighting active tab
if i + 1 == tabpagenr()
let ret .= '%#errorMsg#'
else
let ret .= '%#TabLine#'
endif
" find the buffername for the tablabel
let buflist = tabpagebuflist(i+1)
let winnr = tabpagewinnr(i+1)
let buffername = bufname(buflist[winnr-1])
let filename = fnamemodify(buffername,':t')
" check if there is no name
if filename == ''
let filename = 'noname'
endif
" only show the first 6 letters of the name and
"… if the filename is more than 8 letters long
if strlen(filename) >=8
let ret .= '['. filename[0:5].'..]'
else
let ret .= '['.filename.']'
endif
endfor
" after the last tab fill with TabLineFill and reset tab page #
let ret .= '%#TabLineFill#%T'
return ret
endfunction
+1
apkawa #
Замена текста во всех буферах:

:bufdo %s/pattern/substitution/ge | update
0
spxnezzar #
Спасибо… еще один маленький шаг в переходе на vim для меня.
+1
DarkestMaster #
Пользуюсь vim-ом время от времени на примитивном уровне по необходимости.

Прочитав статью, понял, что использование подобных финтов на автопилоте сравнимо с владением техники карате на уровне первого дана. Количество нюансов, конечно, воображение потрясает, но понимаешь, что шансов дотянуться до подобной виртуозности крайне мало.
0
BEERsk #
это точно не про меня. выучил только базовые возможности vim'а, только те которые сильно влияют на производительность труда (все от лени-матушки, от неё, родимой). вообще думаю, что реально в голове оседает только то, чем пользуешься сравнительно часто.

я например свой vimrc практически не менял, как писать vim-функции — не знаю. да и вообще много чего не знаю в этом редакторе, но то что знаю — очень здорово помогает в работе, избавляя от рутинной, монотонной работы, делая её немного творческой и даже забавной.

думаю, что у каждого есть свой «набор» похожих знаний и умений в «базовых» продуктах — таких как vim, bash, coreutils,… — те которые нужны в ежедневной работе и позволяют не отвлекаться на рутину.

надеюсь что своей статьей помог хотя-бы кому-нибудь дополнить свой «набор» и сделать свою работу хоть чуточку веселее, продуктивней
0
flashvoid #
Веселее стало — спасибо.
0
mahoro #
На самом деле страшновато делать изменения в буферах, которые не видишь своими глазами, особенно если изменения несколько сложнее, чем вставка одной строки (с -o в реальности никогда файлы не открываю, только табы)

По старинке и с большим контролем это можно сделать, выполнив записанный макрос с помощью @m, и повторяя его во всех вкладках с помощью @@ — по времени, наверное, не сильно дольше, но совсем не страшно :)
0
iSerpent #
Спасибо за статью, узнал о normal — очень удобная штука. Я не так давно начал учить Vim, сейчас как раз в процессе и чем дальше, тем интереснее :) На днях смотрел скринкаст именно на эту тему — Derek Wyatt на vimeo — Working with Many Files (Screencast 2). Примерно то же самое, только немного другими инструкциями + немного нагляднее.
0
mitry #
Вот так короче, используя однострочник и нерассмотренный argdo (запись макроса в данном случае не нужна)

vim -c ":argdo 1norm! OПервая строка" file1.txt file2.txt file3.txt

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.