Редактирование и вообще обработка текстов - одна из основных операций, выполняемых на компьютерах. Стандартные средства редактирования в ОС UNIX появились давно и ориентированы на простейшие текстовые терминалы. К таким средствам можно отнести строковый редактор ed и экранный редактор vi. При первом знакомстве они могут показаться сложными и явно устаревшими с точки зрения "дружественности", однако в мире UNIX хорошо не то, что является самым новым и "красивым", а, скорее, то, что используется давно, многими людьми и есть в любой версии. Это в полной мере относится к стандартным средствам обработки текстов.
Эффективность обработки текста определяется эффективностью поиска необходимых фрагментов. Для задания образцов поиска в ОС UNIX используется ряд метасимволов регулярных выражений, впервые появившихся в редакторе ed и представленных в табл. 19.
Таблица 19. Метасимволы регулярных выражений
| Метасимвол | Описание |
| c | Любой конкретный символ задает совпадение с таким же символом |
| \c | Отменяет специальный смысл символа c |
| ^ | Соответствует началу строки, когда ^ начинает образец |
| $ | Соответствует концу строки, когда $ заканчивает образец |
| . | Совпадает с любым одиночным символом |
| [...] | Соответствует одному любому символу в ...; допустимы диапазоны типа a-z |
| [^...] | Соответствует любому одиночному символу, не входящему в ...; допустимы диапазоны |
| r* | Соответствует нулевому или более числу вхождений r, где r - символ или [...] |
| & | Используется только в правой части команд замены (s); вставляет фрагмент, совпавший с образцом |
| \(...\) | Помечает регулярное выражение; найденные строки доступны как \1, \2 и т.д. до \9 в левой и правой частях соответствующей команды замены s, а также в шаблонах поиска сразу после закрытия соответствующей круглой скобки. |
Простые примеры регулярных выражений и задаваемых ими шаблонов поиска представлены в табл. 20.
Таблица 20. Примеры использования регулярных выражений
| Образец | Соответствие |
| /^$/ | пустая строка, т.е. только конец строки |
| /./ | непустая строка, по крайней мере один символ |
| /^/ | все строки |
| /thing/ | thing где-либо в строке |
| /^thing/ | thing в начале строки |
| /thing$/ | thing в конце строки |
| /^thing$/ | строка, состоящая лишь из thing |
| /thing.$/ | thing плюс любой символ в конце строки |
| /\/thing\// | /thing/ где-либо в строке |
| /[tT]hing/ | thing или Thing где-либо в строке |
| /thing[0-9]/ | thing, за которой идет одна цифра |
| /thing[^0-9]/ | thing, за которой идет не цифра |
| /thing1.*thing2/ | thing1, затем любая строка, затем thing2 |
| /^thing1.*thing2$/ | thing1 в начале и thing2 в конце |
Чтобы манипулировать не только целыми фрагментами, выбираемыми регулярными выражениями, но и их частями, используются помеченные регулярные выражения: если конструкция \(...\) появляется в регулярном выражении, то часть соответствующего ей фрагмента доступна как \1. Допускается использование до девяти помеченных выражений, на которые ссылаются \1, \2 и т.д.
Вот ряд примеров использования помеченных регулярных выражений:
| s/\(...\)\(.*\)/\2\1/ | Поместить 3 первых символа в конец строки |
| /\(..*\)\1/ | Найти строки, содержащие повторяющиеся смежные цепочки символов |
| s/^\(..*\)\.\(..*\)/\1.\ \2/ | Перенести остаток строки после первой точки на следующую строку |
Программы семейства grep осуществляют поиск шаблона (задаваемого на языке регулярных выражений) в указанных файлах или во входном потоке и (обычно) выдают соответствующие шаблону строки в выходной поток. В это семейство входят три программы, grep, egrep и fgrep, отличающиеся алгоритмами (а, значит, скоростью работы и используемыми ресурсами системы) и, частично, возможностями при задании шаблонов.
Вызов команды grep имеет следующий синтаксис:
Команда ищет строки, задаваемые шаблоном в виде ограниченного регулярного выражения (используют подмножество допустимых алфавитно-цифровых и специальных символов), аналогичного используемым в ed, в указанных файлах или во входном потоке. Возможные опции приведены в табл. 21.
Таблица 21. Опции командной строки grep
| Опция | Назначение |
| -b | Перед каждой строкой выдавать номер блока, в котором она найдена. Это может пригодиться при определении номера блока по контексту |
| -c | Выдавать только количество строк, соответствующих шаблону |
| -i | Игнорировать разницу между прописными и строчными буквами |
| -h | Предотвращает выдачу имени файла перед совпавшей строкой. Используется при многофайловом поиске. |
| -l | Выдавать имена файлов, содержащих совпавшие строки, один раз, разделяя их переводом строки. Не повторяет имена файлов, если шаблон найден более одного раза. |
| -n | Предваряет каждую строку ее порядковым номером (первая строка имеет номер 1) |
| -s | Подавляет выдачу сообщений об ошибках, связанных с не существованием файлов или недоступностью для чтения |
| -v | Выдает все строки, кроме тех, что содержат шаблон |
| -e se | Ищет специальное выражение se (полное регулярное выражение, начинающееся с -) |
| -f файл | Берет список полных регулярных выражений из файла |
Будьте внимательны при использовании символов $, *, [, ^, |, (, ) и \ в шаблоне, так как они также имеют значение для командного интерпретатора. Лучше заключать искомый шаблон в апострофы: '...'.
Статус выхода равен 0, если найдены совпадающие строки, 1 - если строки не найдены и 2 если имеется синтаксическая ошибка или недоступные файлы (даже если совпадения найдены).
Рассмотрим простые примеры:
[kravchuk@arturo 17:30:29 /]$ echo abc abc | grep '\([abc][abc]*\) \1'
abc abc
[kravchuk@arturo 17:31:13 /]$ echo abc abc | grep 'c a'
abc abc
[kravchuk@arturo 17:31:22 /]$ echo abc abc | grep '^c a'
[kravchuk@arturo 17:31:26 /]$ cd $INFORMIXDIR/etc
[kravchuk@arturo 17:31:45 /usr/inf.731/etc]$ grep -n $INFORMIXDIR
^C
[kravchuk@arturo 17:32:03 /usr/inf.731/etc]$ grep -n tmp *.sh
beta_evidence.sh:306: DUMPDIR=/tmp
bldutil.sh:40:# remove tmp salvage_file
bldutil.sh:55: RESFILE=/tmp/bldutil.$$
evidence.sh:302: DUMPDIR=/tmp
logevent.sh:46:TMPFILE=${TMPDIR:-/tmp}/$PROG.`date +%y-%m-%d-%H%M-%S`
vi (vedit) - экранно-ориентированный текстовый редактор. Он позволяет видеть одновременно целую страницу текста, перемещаться по нему курсором и непосредственно видеть вносимые изменения.
Редактор vi является наследником строкового редактора ex, который, в свою очередь, является расширением базового текстового редактора ed. Тем самым, обеспечивается преемственность средств редактирования и использование эффективного механизма поиска и замены на базе регулярных выражений.
Для вызова редактора vi в простейшем случае используется следующий синтаксис:
В результате, указанный файл открывается в окне редактора. Если файл не указан, редактируется первоначально пустой буфер (т.е. новый файл, имя которого первоначально не задано).
Строку, на которой открывается файл, можно задавать следующим образом:
| +номер | Строка с указанным номером |
| + | Последняя строка файла |
| +/re | Строка, соответствующая указанному регулярному выражению re |
Указанная строка будет находиться в центре экрана (если только файл не меньше, чем размер экрана) и в ее начале будет установлен курсор.
Редактор vi поддерживает несколько режимов работы:
| Командный режим | Нормальный и начальный режим. По завершении других режимов происходит возврат в командный режим. Для форсированного перехода в этот режим используется клавиша Esc |
| Режим ввода | В режим ввода входят при задании одной из следующих команд: a A i I o O c C s S R. При этом может набираться произвольный текст. Из этого режима выходят либо по Esc, либо он автоматически прерывается редактором. При этом обычно подается звуковой сигнал. |
| Режим последней строки | Чтение ввода для команды : / ? или !; прекращается нажатием клавиши Enter. |
Основные команды редактора vi представлены в табл. 22.
Таблица 22. Сводка основных команд редактора vi
| Перемещение курсора | |
| H (Ctrl-h) | курсор влево |
| J (Ctrl-n) | курсор вниз |
| K (Ctrl-p) | курсор вверх |
| L (Space) | курсор право |
| Ctrl-u | Переход вверх на половину экрана |
| Ctrl-d | Переход вниз на половину экрана |
| Ctrl-f | На страницу вперед (PageDn) |
| Ctrl-b | На страницу назад (PageUp) |
| 0 | Переход в начало текущей строки |
| $ | Переход в конец текущей строки |
| nG | Переход на строку с номером n |
| Добавление текста | |
| a | Добавить текст после курсора |
| A | Добавить текст в конце текущей строки |
| i | Вставить текст перед курсором |
| I | Вставить текст в начале текущей строки |
| o | Образовать новую строку под текущей |
| O | Образовать новую строку над текущей |
| Изменение текста | |
| ~ | Изменить регистр символа над курсором |
| r | Замена одного символа |
| R | Замена символов |
| Удаление текста | |
| x | Удаление символа |
| dd | Удаление строки |
| Ndd | Удаление N строк |
| Поиск и замена | |
| /str | Поиск строки str вперед. str может быть регулярным выражением |
| ?/str | Поиск строки str назад |
| n | Повторить поиск в том же направлении |
| N | Повторить поиск в обратном направлении |
| :[range]s/old/new/[g] | Заменить old на new в указанном диапазоне строк range. new и old могут быть регулярными выражениями, а range задается аналогично диапазону строк в редакторе ed. Суффикс g означает заменить во всем файле. |
| Копирование текста | |
| yy | Копирование строки в целом |
| Nyy | Копирование N строк |
| p | Вставить из буфера после (курсора, текущей строки) |
| P | Вставить из буфера перед (курсором, текущей строкой) |
| Выход из редактора | |
| :wq ENTER | Запись и выход. Записать текст из буфера в файл и выйти из редактора. |
| :x ENTER | Условная запись и выход. Записать текст из буфера только при наличии изменений и выйти из редактора. |
| :q! ENTER | Закончить редактирование без записи изменений. |
| Другие команды | |
| ! | Выполнить одну команду интерпретатора |
| . | Повторить последнюю команду |
| u | Отменить действие последней команды |
| J | Соединить строки |
| Ctrl-G | Показать номер текущей строки |
Курсор можно перемещать и клавишами перемещения курсора или клавишами PageUp, PageDn, но эти возможности, в отличие от описанных в таблице, поддерживаются не на всех терминалах.