Описание: по умолчанию в системах BSD используется редактор vi(1) многие системные утилиты используют его в своей работе. Кандидат BSDA должен уметь использовать этот редактор: редактировать файлы, редактировать файлы доступные только для чтения, выходить из редактора без сохранения.
Практика: vi(1) including: :w, :wq, :wq!, :q!, dd, y, p, x, i, a, /, :, :r, ZZ, :set number, :set list
Тем, кто сталкивается с vi(1) впервые, может показаться, что программист написавший его был сумасшедшим. Я знаю человека, который утверждал, что при его первом знакомстве с vi(1) он не смог из этого редактора выйти и был вынужден... перезагрузить компьютер reset'ом (ну и кто, спрашивается сумасшедший, программист или пользователь?). vi(1) упомянут в качестве текстового редактора в стандарте POSIX. По этой причине vi(1) есть в любой операционной системе семейства UNIX (принимая во внимание оговорки из следующих двух абзацев). Так что надо сжать зубы и выучить vi(1). Без этого никуда.
Небольшое замечание про vi(1) и
vim(1). В мире существует огромное множество
клонов редактора vi(1). В стандарте
POSIX описаны некоторые свойства редактора
vi(1), но конечно не настаивается на том,
чтобы люди использовали именно vi(1) и ни что
другое. Просто в каталоге /usr/bin/
должно
располагаться нечто под названием vi(1),
обладающее такими-то свойствами. Пользователям же хотелось,
чтобы текстовый редактор как-то развивался, добавлялись новые
функции: синтаксическая подсветка, работа с текстами набранными
в различных кодировках, фолдинг и многое другое. Потому-то и
существует множество клонов стандартного
vi(1). Одним из самых удачных и
распространённых является редактор vim(1),
написанный голландским программистом Брамом Мооленааром (Bram
Moolenaar). Название vim расшифровывается как
Vi iMproovement т.е. усовершенствованный
vi(1). Это чрезвычайно мощное средство
редактирования текстов. Если вам кажется, что
vim(1) чего-то не умеет, значит вы не дочитали
документацию до конца. Весь этот документ, кстати, написан в
vim(1). Что особенно приятно,
vim(1) портирован во все мыслимые
операционные системы (кроме откровенно эзотерических) и везде
ведёт себя одинаково.
Текстовый редактор vim(1) написан как полная
замена vi(1). В нём есть режим работы
полностью эмулирующий vi(1) «за
исключением явных ошибок», как пишет об этом Брам. В
большинстве дистрибутивов Linux текстовый
редактор vi(1) заменён на
vim(1). vim(1)
запускается под именем vi(1) и входит в
vi-compatible режим. Это не единственное место, где авторы
дистрибутивов Linux вольно обращаются с
утилитами входящими в POSIX. Другими такими
примерами являются sh(1) и
awk(1), заменённые на
bash(1) и gawk(1), но
запускающиеся по соображениям совместимости под старыми именами.
Во всех BSD системах в каталоге
/usr/bin
находится оригинальный
vi(1). vim(1) доступен
только как сторонний продукт и устанавливается из портов.
Кроме vi(1) существует множество более
простых редакторов с более или менее очевидным поведением.
Большинство из них устанавливается в виде отдельных портов,
однако некоторые входят в стандартный комплект и поставляются
вместе с операционной системой. Например с
FreeBSD поставляется редактор
ee(1), написанный в расчёте на то, что с ним
сможет работать любой человек, совершенно ничему не обученный.
Но все системные утилиты без указания переменной окружения
EDITOR
будут вызывать именно
vi(1).
Важно | |
---|---|
В данном разделе описан не vim(1), а
vi(1) версии 1.79 (10/23/96) The CSRG,
University of California, Berkeley. Эта версия сама по себе,
обладет некоторыми особенностями отсутсвующими в
POSIX-vi. Например,
описываемый vi(1) обладает опцией searchinc и
возможностью редактирования текста в нескольких окнах
(:N ).
|
Основное отличие vi(1) от прочих текстовых редакторов — невозможность набирать текст непосредственно после запуска. Я настоятельно рекомендую новичкам установить порт vim(1) и выполнить команду vimtutor(1). Таким образом, вы познакомитесь с основными клавишами vi(1) и режимами работы. На худой конец, прочтите этот раздел до конца прежде чем приметесь за эксперименты.
vi(1) имеет несколько режимов работы:
Очень важным элементом работы в vi(1) является «движение». Важно уметь передвигаться в vi(1) не посимвольно, при помощи стрелочек, а именно при помощи его буквенных команд, упомянутых ниже. В комбинации с другими командами это даст вам большие возможности по редактированию текста.
Таблица 7.2. Движения в vi(1), Normal mode
Команда | Мнемоника | Описание |
---|---|---|
h j k l | нет | Это клавиши посимвольного перемещения, тождестенные стрелкам. Стрелки есть не на всех клавиатурах, кроме того, для людей владеющих слепым набором такой способ перемещения удобен, так как им не приходится снимать руки с клавиатуры, для того, чтобы добраться до нужного символа. |
w | word | Перемещение к началу следующего слова |
W | WORD | Перемещение к началу следующего слова, но под словом подразумевается не совокупность букв, а совокупность непробельных символов. Таким образом, URL http://www.vim.org/ состоит из нескольких слов, но из одного СЛОВА. |
e | end | Перемещение вперёд, к концу слова |
E | END | Перемещение вперёд, к концу СЛОВА |
b | begin | Перемещение назад, к началу слова |
B | BEGIN | Перемещение назад, к началу СЛОВА |
n | next | Применяется после поиска в Search mode. Повторить поиск вперёд. |
N | нет | Повторить поиск назад. |
} | нет | Перемещение в конец абзаца |
{ | нет | Перемещение в начало абзаца |
) | нет | Перемещение в конец предложения |
( | нет | Перемещение в начало предложения |
0 | нет | Перемещение в начало строки |
^ | нет | Перемещение к первому символу в строке |
$ | нет | Перемещение в конец строки |
+ | нет | Перемещение в начало следующей строки |
- | нет | Перемещение в начало предыдущей строки |
f<letter> | find | Перемещение на следующий в строке символ <letter> |
F<letter> | find | Перемещение на предыдущий в строке символ <letter> |
t<letter> | till | Перемещение на позицию предшествующую следующему в строке символу <letter> |
T<letter> | till | Перемещение на позицию следующую сразу за предыдущим в строке символом <letter> |
; | нет | повторить последнее движение заданное клавишами f, F, t, или T |
, | нет | То же, что ; но в другом направлении |
% | нет | Перемещается на скобку соответствующую той, что под курсором |
Перед движением можно вводить числовой префикс. Например: 3} — переместиться на 3 абзаца вниз.
Если перед движением указать некоторое действие, то оно будет проделано с той областью текста, через которую проходит курсор при движении. Например: dw — стереть слово.
Таблица 7.3. Действия в vi(1), Normal mode
Команда | Мнемоника | Описание |
---|---|---|
<move>d | delete | Удалить текст, через который осуществлялось движение. При удалении текст помещается в буфер |
dd | delete | Удаляет целиком текущую строку |
D | delete | Удаляет текст от текущего символа до конца строки |
<move>y | yank | Поместить текст через который осуществлялось движение в буфер (не удаляя) |
yy | yank | Поместить в буфер целиком текущую строку |
Y | yank | То же, что и yy, как ни странно |
<move>c | change | Удалить текст через который осуществлялось движение и немедленно перейти в Insert mode |
cc | change | Удалить текущую строку и немедленно перейти в Insert mode |
C | change | Удалить текст от текущей позиции до конца строки и немедленно перейти в Insert mode |
p | paste | Вставить текст из буфера |
P | paste | Вставить текст из буфера слева от курсора |
x | нет | Удалить символ под курсором. (На заметку: сочетание клавиш xp меняет местами два символа. Почему?) |
X | нет | Удалить символ слева от курсора (как клавиша BackSpace) |
~ | нет | Инвертировать регистр букв (строчная буква меняется на прописную, а прописная на строчную). Например сменить UNIX на unix: 4~ |
r<letter> | нет | Заменить символ находящийся под курсором на <letter> |
< <move> | нет | Уменьшить отступ у текста захваченного движением <move> |
> <move> | нет | Увеличить отступ у текста захваченного движением <move> |
U | undo | Отменить последнее действие. В vi(1) можно сделать многократное undo, весма нетривиальным способом, на первый взгляд оно кажется однократным[a]. В vim(1) объём undo можно задать любым. |
. | нет | Повторить последнее действие |
i | insert | Вход в Insert mode слева от курсора |
I | insert | Вход в Insert mode в начале строки |
a | append | Вход в Insert mode справа от курсора (это удобно, если вы переместились в конец слова клавишей e) |
A | append | Вход в Insert mode в конце строки |
R | insert | Вход в Replace mode (то же, что Insert, но при наборе символы замещают текст) |
o | нет | Добавить строку под курсором, встать на неё и войти в Insert mode |
O | нет | Добавить строку над курсором, встать на неё и войти в Insert mode |
/ | нет | Вход в Search mode для поиска вперёд |
? | нет | Вход в Search mode для поиска назад |
ZZ | нет | Записать файл и выйти |
[a] Если вы в
vi(1), в Normal mode нажимаете
клавишу « |
Например, если у нас есть надпись <entry>НАДПИСЬ</entry> и нам надо заменить её на <entry>ЬСИПДАН</entry> мы встаём на начало строки и выполняем такое действие: f>lct<ЬСИПДАН правда всё просто и очевидно? Потренируйтесь, обещаю вам, что через неделю вы перестанете понимать как вы до сих пор обходились без vi(1).
Из Insert mode главное — уметь выходить. Для этого есть миниму два способа: <Esc> или Ctrl+C. Последнее удобнее по эргономичным соображениям.
Вас может удивить, что в vi(1) в Insert mode не всегда можно перемещаться стрелками, не всегда работает BackSpace. Научитесь пользоваться «родными» клавишами vi(1) — их главное преимущество состоит в том, что они работают всегда на всех терминалах, заходите ли вы с чужого макинтоша на тостер под управлением NetBSD или запустили экзотический эмулятор терминала и держите в руках клавиатуру SUN на которой все кнопки другие, а видете её первый (и быть может последний) раз в жизни.
Поиск в vi(1) осуществляется либо вперёд, либо назад. Соответственно вход в этот режим осуществляется клавишими / или ?. Выход, так же как и из Insert mode — <Esc> или Ctrl+C.
vi(1) осуществляет поиск при помощи регулярных выражений. В vim(1) их возможности были сильно расширены. В настоящий момент возможности регулярных выражений в vim(1) даже превосходят возможности регулярных выражений в perl(1). К сожалению, работают они значительно медленнее. Но мы рассматриваем не vim(1), а чистый vi(1).
Таблица 7.4. Регулярные выражения в vi(1)
Оператор | Описание |
---|---|
. | любой символ |
[abc] | любой символ из указанного набора |
[^abc] | любой символ отсутствующий в указанном наборе |
<atom>* | «квантификатор» — vi(1) ищет сколько угодно вхождений <atom'а> |
\ | Экранирование последующего символа, например, если нам надо найти текст a* мы должны искать a\*, чтобы * не была интерпретирована как квантификатор |
Увы, в изначальном vi(1) синтаксис регулярных выражений не был столь развит как в современном vim(1).
В vi(1) FreeBSD можно выставить переменную searchinc (как именно, сказано ниже) и тогда поиск станет инкрементным (т.е. курсор будет перемещаться в процессе набора текста в строке поиска). В vim(1) для этого служит переменная incsearch. По всей видимости, какие-то усовершенствования в vi(1) всётаки вносились...
Некоторые действия можно выполнить в vi(1) только с командной строки. Например задание значения переменной. Вход в командную строку осуществляется из Normal mode клавишей :. Переменные могут принимать числовые значения, а могут выставляться в истину или ложь. В последнем случае они должны задаваться с префиксом no:
Многие команды можно задавать не полностью выписывая имя команды, например :r, :re, :rea и :read это одна и та же команда. Такое имя мы будем записывать так: :r[ead]
Опции тоже могут записываться сокращённо. Таким образом, команды :set nonumber и :se nonu эквивалентны.
Таблица 7.5. Некоторые команды vi(1)
Команда | Описание |
---|---|
:se[t] <option> | управляет переменными (см. выше в тексте) |
:r[ead] <file> | Читает <file> и вставляет его содержимое после курсора |
:r[ead]!<cmd> | Выполняет в команду <cmd> и вставляет её вывод после курсора |
:!<cmd> | Выполняет в команду <cmd> |
:w[rite] [file] | Записать file, если file не указан, записывается текущий файл (т.е. как «кнопка Save») |
:w[rite]! [file] | То же, что и :w, но позволяет перезаписать файл открытый в режиме «только для чтения» (например, если вы владелец файла и у вас на него пермиссии r--, vi(1) временно изменит их на rw-). |
:q[uit] | Выйти из редактора (без сохранения) |
:q[uit]! | Выйти из редактора (без сохранения) даже если текст был изменён |
:wq, :x ZZ | Записать файл и выйти из редактора (ZZ в Normal mode) |
:wq!, :x! | Записать файл даже если он был открыт в режиме «только для чтения» (см. выше) и выйти из редактора |
:[range]s[ubstitute]/pattern/subst/[flags] | В строках из указанного диапазона искать pattern и заменять его на subst. Если диапазон не указан, замена осуществляется только в текущей строке, если указан флаг g замена производится любое количество раз в каждой строке (иначе заменяется только первое вхождение). Диапазон может указываться в формате n,m (где n и m — номера строк или специальные символы: . — текущая строка, $ — последняя строка в файле). Чтобы произвести замену во всём файле надо указать диапазон 1,$ или %. |
:ve[rsion] | Напечатать версию редактора vi(1) |
:N <file> | Разбить окно на две части и открыть файл во втором окне. Переключаться между окнами Ctrl+w. Внимание! Этой функции нет в POSIX vi(1). В vim(1) это делается другим способом. Эта функция есть только в описываемой версии vi встроенной в FreeBSD. |
В приведённой ниже таблице перечислены некоторые опции vi(1). если в поле «тип» написано bool, это значит, что переменная имеет логическое значение и устанавливается командой :set option или :set nooption. Если в столбце POSIX стоит «-», то этой опции нет в POSIX-vi, она есть только в описываемой версии vi(1) FreeBSD и с высокой вероятностью в vim(1) эта опция выставляется другим способом.
Таблица 7.6. Некоторые опции vi(1) выставляемые командой :set
Опция | Тип | POSIX | Описание | |
---|---|---|---|---|
краткая | полная | |||
list | list | bool | + | Видоизменяет отображение файла таким образом, чтобы пользователь мог отличить пробелы от табуляторов |
nu | number | bool | + | Отображает номера строк |
ts | tabstop | integer | + | задаёт ширину табулятора |
sw | shiftwidth | integer | + | задаёт величину отступа добавляемую, например, командой > |
searchinc | searchinc | bool | - | включает инкрементный поиск |
ruler | ruler | bool | - | Отображает номер строки и колонки в нижней строке экрана |
ic | ignorecase | bool | + | Неразличать регистр при поиске |
ro | readonly | bool | + | Файл открыт в режиме «только для чтения» |
ws | wrapscan | bool | + | При поиске, по достижении конца файла, продолжить поиск с начала до курсора. Т.е. искать во всём файле. |
Надо честно признаться, я не осветил возможностей vi(1) и на 20%, не говоря уже о vim(1). С другой стороны, объём сведений данных здесь достаточен для повседневной работы и для сдачи экзамена BSDA.