83
6. РЕДАКТОР ТЕКСТОВ ED
6.1. Введение
Редактор текстов ed является диалоговой (интерактивной)
программой, которая позволяет добавлять, перемещать, удалять
текст и извлекать его из других файлов. Имеется возможность
замены слова или части слова в тексте как для одной
указанной строки, так и для части файла или всего файла.
Кроме того, можно просмотреть текстовый файл, напечатать его
частично или целиком, напечатать строки, содержащие
определенное слово и т.д.
ed работает с копией обрабатываемого файла, которая
создается в буфере редактора и хранится там в течение всей
обработки. Это предохраняет исходный файл от возможных
разрушений при совершении грубых ошибок. Сделанные в копии
изменения не влияют на исходный файл до тех пор, пока не
будет выдана команда записи.
Редактор запоминает имя обрабатываемого файла
(первоначально - имя исходного загруженного файла). По
желанию пользователя это имя можно заменять для получения
новых вариантов файла.
Если размер файла превышает размер буфера редактора,
файл приходится делить на части с помощью команды split,
редактировать его по частям, а затем снова объединять с
помощью команды cat.
Пользователь сообщает редактору, что делать с его
текстом, с помощью определенных инструкций, называемых
"командами". Команды редактора имеют простую структуру, и в
большинстве случаев состоят из одной буквы. Каждая команда
печатается на отдельной строке. Иногда перед командой
указывается информация о том, какая строка или строки должны
подвергаться действию команды. ed не отвечает на большинство
команд, не печатает подсказки или сообщения типа "готово".
Все вводимые командные строки должны заканчиваться
символом .
6.2. Вызов редактора
Синтаксис команды:
ed [файл]
где файл - имя файла.
Если файл с указанным именем существует, в ответ будет
выдано число символов в файле. В противном случае редактор
выдает строку "?file".
6.2.1. Дозапись текста
Если создан пустой файл и необходимо записать в него
некоторый текст, следует установить режим дозаписи командой:
a
в ответ система переведет курсор на новую строку.
Для отмены режима дозаписи в первой позиции строки
вводится команда "." (точка) , за которой следует символ
84
"конец строки" ().
Символ "." в любой другой позиции не является командой,
воспринимается как часть вводимого текста и не приводит к
выходу из режима дозаписи.
6.3. Запись файла
Во время работы ed текст находится во временном буфере
редактора и, чтобы сохранить его, по концу редактирования
необходимо записать содержимое буфера в файл. Для этой цели
используется команда записи.
Формат команды:
w[файл]
где файл - имя файла, в который требуется произвести
запись.
Если имя файла опущено, запись производится в текущий
файл. В результате работы команды содержимое буфера будет
скопировано в файл (предыдущая информация в файле будет
уничтожена) и выдано сообщение о количестве символов в
файле. Если в ответ на попытку записи появляется сообщение
"?имя_файла", это означает, что запись в данный файл или
справочник закрыта.
При записи файла создается копия текста - содержимое
буфера не изменяется, так что можно продолжить работу.
Рекомендуется время от времени записывать содержимое буфера,
т.к. в случае сбоя системы или совершения какой-либо ошибки
весь находящийся в буфере текст может быть потерян.
6.4. Выход из редактора
Данная команда используется для завершения
редактирования текста и выхода из редактора.
Формат команды:
q
Так как буфер редактора при выполнении команды "q"
уничтожается, для сохранения результатов редактирования
буфер должен быть предварительно скопирован командой записи
"w".
Если после изменения информации не была выполнена
команда записи, в ответ на первую команду "q" выдается
подсказка "?" и никаких действий не производится. При
повторном наборе команды осуществляется выход с уничтожением
накопленной в буфере информации.
6.5. Чтение файла
6.5.1. Команда редактирования файла (e)
Формат команды:
e имя_файла
По данной команде файл с именем "имя_файла" копируется
в буфер редактора. Предыдущее содержимое буфера при этом
теряется.
Редактор сохраняет имя скопированного в буфер файла,
благодаря чему после завершения редактирования файла нет
85
необходимости задавать его имя в команде записи "w". Команда
"w" произведет запись именно в этот файл.
Команда языка shell:
ed имя_файла
эквивалентна командам
ed
e имя_файла
По завершению чтения файла выдается размер считанного файла
(в байтах).
6.5.2. Команда чтения файла (r)
Формат команды:
[n]r имя_файла
где n - номер строки в буфере, после которой
помещается файл.
Команда "r" читает содержимое файла в буфер редактора,
причем содержимое файла добавляется к тому, что уже хранится
в буфере.
Если "n" отсутствует, то читаемая информация
дописывается после последней строки, хранящейся в буфере, в
противном случае, считываемый файл помещается после строки с
номером "n".
Если имя файла отсутствует в команде, то считывается
файл, имя которого является текущим.
По завершению чтения редактор выдает размер считанного
файла (в байтах).
6.6. Печать текста
6.6.1. Команда печати (p)
По данной команде производится выдача строк файла,
находящегося в буфере редактора.
Формат команды:
[n[, k]]p
где n, k - номера начальной и конечной печатаемых строк.
Команде "p" может предшествовать один или два номера
строки. Если номер не задан, то редактор печатает текущую
строку.
Если задан номер только одной строки (с последующей
буквой "p" или без нее), то печатается одна заданная строка
(и она становится текущей).
Если задано два номера строки, то печатаются все строки
в указанном интервале (текущей строкой становится последняя
выданная строка). При задании номеров двух строк первый
номер не может быть больше второго.
Вы можете таким образом распечатать весь файл. Если вы
не знаете номер последней строки, то поставьте символ $.
Примеры.
1,2p - печать первых двух строк буфера;
1,$p - печать всех строк буфера; символ $ используется для
обозначения последней строки буфера;
$-1, $p - печать двух последних строк буфера; dfn .-3, -1p
печать трех предыдущих строк.
В сущности, команде "p" могут предшествовать 0, 1 или 2
86
номеров строк. Если номера строк не указаны, печатается
текущая строка. Однократное нажатие клавиши вызывает
печать следующей строки: оно эквивалентно команде ".+1p".
Команда "-" эквивалентна команде ".-1p".
6.6.2. Команда печати (l)
Команда "l" аналогична команде "p", но предоставляет
больше информации. Ее главным свойством является то, что она
печатает управляющие символы, такие как символы табуляции
(tab) и возврата на позицию (backspace). Кроме того, команда
"l" переносит строки при печати. Например, любая строка,
длина которой превышает 72 символа, печатается на нескольких
строках. Чтобы указать, что строка была перенесена и где она
была перенесена, в конце каждой части переносимой строки
вставляется обратная дробная черта (\).
Некоторые управляющие символы:
- символ табуляции - печатается как ">";
- код возврата на позицию - печается как "<";
- код перехода на новый лист - печатается как "\14";
- код вертикальной табуляции - печатается как "\13";
- "звуковой сигнал" - печатается как "\07";
- код "новая строка" - печатается как "\n".
6.7. Просмотр файла
Редактор запоминает последнюю строку, с которой
производились какие-либо действия, так что она может
использоваться без явного указания номера строки. Ссылка на
эту строку производится с помощью символа ".".
Точка обозначает номер текущей строки. Ее можно
использовать различными способами. В частности, можно
ввести:
., $p
это приведет к распечатке всех строк от текущей строки до
конца буфера включительно.
Точка наиболее полезна при использовании в комбинациях
следующего вида:
.+1 (или, что то же самое .+1p)
это означает "напечатать следующую строку" и представляет
собой удобный способ медленного просмотра буфера. Можно
также ввести команду:
.-1 (или .-1p)
что означает "распечатать строку перед текущей строкой". Это
позволяет, при желании, двигаться назад.
Еще одной полезной командой является команда вида:
.-3, .-1p
которая распечатывает три предшествующие строки.
Необходимо помнить о том, что обе команды печати "p" и
"l" изменяют номер текущей строки. Можно в любое время
узнать ее значение, введя:
.=
редактор ответит печатью значения номера текущей строки.
6.7.1. Команда печати (n)
Команда печати n распечатывает текст и предваряет
87
каждую строку текста номером по порядку. Эту команду полезно
использовать перед удалением, созданием или изменением
строк.
Формат команды:
[n[, k]]n
где n, k - номера начальной и конечной печатаемых строк.
Пример использования клманды "n":
Пример.
1, $n
1 This is the first line of test.
2 This is the second line.
3 This is the third line.
4 This is the fourth line.
5 five
6 six
7 seven
8 eight
9 nine
10 ten
6.8. Команда удаления строк (d)
Данная команда предназначена для удаления одной или
группы строк в буфере редактора.
Формат команды:
[n[, k]]d
где n, k - номера начальной и конечной удаляемых строк.
Команде "d" может предшествовать один или два номера
строки. Если номер не задан, то редактор удаляет текущую
строку.
Если задан номер только одной строки, то удаляется
указанная строка, текущей становится строка, следующая за
удаленной.
Если задано два номера строки, то удаляются все строки
в указанном интервале от n до k включительно. Текущей
строкой всегда становится строка, следующая за последней
удаленной строкой, кроме случая, когда удаляется последняя
строка буфера. В этом случае текущей станет последняя строка
буфера.
Пример.
4, $d - удаление из буфера строк с 4-й по последнюю
включительно. В буфере после выполнения команды
останется 3 первых строки. Текущей строкой станет
третья строка буфера.
6.9. Команда отмены редакции (u)
В некоторых случаях обнаруживается, что внесенные
изменения не были необходимы или оказались неверными.
Команда отмены редакции может быть использована для
приведения только что измененной строки в ее исходное
состояние:
u
Например, команда u полезна для восстановления текста,
случайно вами удаленного. Если вы удалили все строки в файле
и затем ввели команду "p", редактор ed ответит "?", что
означает, что в файле нет ничего. Воспользуйтесь командой u
для восстановления текста. Экран будет выглядеть следующим
88
образом:
1, $p
This is the first line.
This is the middle line.
This is the last line.
1, $d
p
?
u
p
This is the last line.
Примечание. Команда u не может быть использована с
командой w или q.
6.10. Команда замены (s)
Команда замены "s" предназначена для изменения
отдельных слов или символов в пределах одной строки или
группы строк.
Общий формат команды:
[n[, k]]s/x/y/[команда]
где x - группа символов или слов в строке, которые
надо заменить (старый текст);
y - группа символов или слов, которые заменяют
старое значение, указанное как "x" (новый
текст);
n, k - номера начальной и конечной строк буфера,
в пределах которых осуществляется замена;
/команда - одна из следующих 4-х команд:
g - заменить каждое появление группы
символов (x) в каждой указанной строке;
l - отобразить последнюю строку замененного
текста, включая непечатаемые символы;
n - отобразить последнюю строку замененного
текста, вместе с номерами строк;
p - отобразить последнюю строку замененного
текста.
Если номера строк не указаны, замена осуществляется в
текущей строке.
Если указан номер только одной строки, то замена
производится только в одной строке.
Для реализации замены в группе строк надо указать
номера начальной (n) и конечной (k) строк, в пределах
которых надо произвести замену.
При выполнении данной команды редактор просматривает
строки, начиная с номера "n" и кончая номером "k"
включительно. При обнаружении в какой-либо из них искомой
группы "x" редактор заменяет ее на "y".
Редактор не печатает результат замены автоматически,
поэтому для контроля рекомендуется вместе с командой замены
задавать команду печати.
Если в командной строке указаны "n" и "k" и команда
печати, то печатается только последняя измененная строка.
Текущей строкой после выполнения команды замены
остается последняя строка, в которой произведена замена
части текста.
Пример.
1, $s/a/a2/p
замена символа "a" на "a2" производится в
89
строках с 1-й по последнюю. Текущей станет
последняя строка, она будет распечатана.
Используя команду "s", можно удалить группу символов
(или один символ) в строке. Для этого команда замены должна
быть задана следующим образом:
s/x//
что фактически означает: заменить группу символов в текущей
строке на "пусто", т.е. просто удалить заданные символы из
строки.
Команда "s" заменяет лишь первую найденную искомую
группу символов в строке. Если же надо заменить все случаи
появления заданной комбинации символов в строке,
используется команда "g":
s/x/y/g
Примеры.
s/c/d/gp
все появления символа "c" в текущей строке
заменить символом "d" и распечатать строку;
1, $s/c/d/gp
замена всех символов "c" на символ "d" во
всем буфере с печатью последней измененной
строки.
В следующем примере содержится ошибка ввода. Пока
строка, содержащая ошибку является текущей, произведите
корректировку в ней. Старый текст: "ai" в слове "airor",
новый текст - "er". Экран выглядит следующим образом:
Пример.
a
In the beginning, I made an airor.
.
.p
In the beginning, I made an airor.
s/ai/er/
Обратите внимание, что ed не дает ответа на команду
замены. Чтобы проверить, что команда выполнилась успешно,
выполните команду "p" или "n" как часть командной строки
замены. .lin В следующем примере команда "n" используется
для проверки того, что слово "file" заменит слово "toad".
Пример.
.p
This is a last toad
s/toad/file/n
1 This is a last file
Чтобы заменить текст в строке, отличной от текущей,
укажите номер строки.
Например, на следующем экране командная строка включает
номер строки, которая будет изменена (строка 1), т.к.
текущей является строка 3.
Пример.
1, 3p
This is a past toad
testing testing
come in toad
.
come in toad
1s/past/test
This is a test toad
Как вы видите, ed напечатал последнюю строку
автоматически после изменения, т.к. последний ограничитель
90
опущен.
Наиболее универсальным средством ed является глобальная
замена. Поместив команду "g" после последнего ограничителя в
командной строке замены, вы сможете заменить каждое
появление шаблона в каждой указанной строке. Заменим строку
"es" на "ES":
u
1, $p
This is a last toad
testing testing
come in toad
testing 1, 2, 3
1, $s/es/ES/g
This is a last toad
tESting tESting
come in toad
tESting 1, 2, 3
Другой способ - это использование глобального шаблона
для поиска вместо указания границ строк:
u
1, $p
This is a test toad
testing testing
come in toad
testing 1, 2, 3
g/test/s/es/ES/g
1, 3p
This is a tESt toad
tESting tESting
come in toad
tESting 1, 2, 3
Рассмотрим следующие шаблоны:
/шаблон
?шаблон
v/шаблон
В следующем примере формат поиска v/шаблон используется
для нахождения строк, которые не содержат шаблон "testing".
Затем команда "s" используется для замены шаблона "in" на
шаблон "out" в этих строках:
v/testing/s/in/out
This is a test toad
come out toad
6.11. Команда поиска контекста
Эта команда предназначена для поиска строки, содержащей
заданный символ, группу символов или группу слов.
6.11.1. Конструкция /.../
Формат команды:
/текст/
где "текст" - искомый текст.
Редактор просматривает буфер, начиная со строки ".+1"
(т.е. следующей за текущей), идет до конца буфера, затем
продолжает поиск с первой строки буфера и до текущей строки
включительно. При обнаружении строки с заданным текстом
редактор распечатывает ее, и эта строка становится текущей.
91
В случае отсутствия в буфере искомого текста редактор
возвращается к текущей строке и печатает символ "?".
Пример.
/lop/
найти в буфере строку, содержащую последова-
тельность символов "lop".
Команда поиска в комбинации с другими командами ("a",
"i", "s", "t", "m") может успешно использоваться для
указания необходимой строки.
Примеры.
/lop/s//loop/p
найти строку, содержащую слово "lop", и заме-
нить его на "loop", затем распечатать эту
строку;
/текст/i
поиск строки, содержащей указанный текст, и
вставка перед найденной строкой.
В команде "s" искомый текст в левой части можно не
указывать.
6.11.2. Конструкция ?...?
Редактор производит поиск не только в прямом, но и в
обратном направлении. Для этого в команде поиска вместо
символа "/" используется символ "?":
?текст?
Это удобно в случае, если при редактировании текста
необходимо вернуться назад.
6.11.3. Продолжение поиска
Если при поиске строки с искомым текстом оказалось, что
это не та строка, то для продолжения поиска нужно задать
команду в виде:
// - продолжить поиск в прямом направлении;
?? - продолжить поиск в обратном направлении.
6.12. Команда вставки строк (i)
Данная команда используется для вставки в текст строк,
вводимых с терминала.
Формат команды:
[n]i
где n - номер строки в буфере редактора, перед которой
надо вставить новые строки.
Если "n" отсутствует, то строки вставляются перед
текущей строкой.
Ввод новых строк с терминала завершается символом "." в
первой позиции.
Текущей строкой после выполнения командыы "i"
становится последняя вставленная строка.
Пример использования команды "i" для вставки 3-х строк
перед 7-й строкой:
Пример.
7i
строка 1
строка 2
92
строка 3
.
6.13. Команда замены строк (c)
Команда используется для замены строки или группы строк
в буфере редактора.
Формат команды:
[n[, k]]c
где n, k - номера начальной и конечной заменяемых строк.
По данной команде редактор удаляет строки с номерами от
"n" до "k" включительно и заменяет их строками, вводимыми с
терминала после команды "c".
Ввод новых строк завершается символом "." в первой
позиции и .
Если в команде указан номер одной строки, заменяется
одна строка.
Если номер строки не указан, то заменяется текущая
строка.
Пример замены строк с ".+1" по последнюю.
Пример.
.+1 $c
... строки текста ...
.
Строки, которые вводятся между командами "c" и ".",
займут место исходных строк между начальной строкой и
конечной строкой. Это наиболее удобно при замене строки (или
нескольких строк), содержащих ошибку.
6.14. Работа со строками
6.14.1. Разбиение строк
Редактор обеспечивает возможность разбиения строки на
несколько более коротких строк путем вставки символов новой
строки. Например, строка:
текст xy текст
может быть разбита на две между символами "x" и "y"
следующим образом:
s/xy/x\
y/
команда:
s/xy/x\
zzz\
y/
разобьет исходную строку на три, при этом будет
добавлена строка "zzz".
6.14.2. Объединение строк (j)
Объединение строк осуществляется с помощью команды "j".
Например, если имеются строки:
текст x
y текст
то установив первую строку текущей и задав команду "j",
93
получим:
текст xy текст
Можно объединить все строки в одну большую строку и
распечатать ее.
6.14.3. Копирование строк (t)
Для копирования строк текста в буфере редактора
используется команда "t".
Формат команды:
[n[, k]]tl
где n, k - номера начальной и конечной заменяемых строк;
t - имя команды копирования;
l - номер строки, после которой размещаются копи-
руемые строки с номерами от "n" до "k" включи-
тельно.
По данной команде строки с номерами от "n" до "k"
включительно пересылаются на место после строки с номером
"l".
Если в команде задан только номер одной строки, то
пересылается строка с указанным номером.
Если номер строки не задан, то пересылается текущая
строка.
Строки с номерами от "n" до "k" включительно
сохраняются на своем прежнем месте.
Команду "t" удобно использовать для создания текстов с
повторяющимися данными.
Пример.
1, 7t15
группу строк с 1-й по 7-ю поместить после
15-й строки.
6.14.4. Перестройка строк
Предположим, что в начале каждой строки файла стоят
имена вида:
Петров П.К.
Иванов С.Б
и т.д., требуется переделать текст таким образом, чтобы
инициалы стояли перед фамилиями, т.е.
П.К. Петров
С.Б. Иванов
Такой результат можно получить с помощью нескольких
команд редактирования, что однако достаточно сложно и может
привести к целому ряду ошибок.
Альтернативный метод заключается в том, чтобы отметить
элементы строки (в данном случае фамилию и инициалы), а
затем переставить эти элементы. Если в левой части команды
подстановки "s" какой-либо элемент образца заключен в "\(" и
"\)", то он запоминается и может использоваться в правой
части команды. В правой части команды обозначение "\1"
относится к тому, что соответствало первой паре \(...\),
"\2" - второй паре и т.д.
Следующая команда:
1, $s/^\([^ ]*\) *\(.*\)/\2 \1/
выполняет нужную работу, хотя ее и трудно прочитать. Первая
пара \(...\) соответствует фамилии, которая представляет
собой любую строку символов вплоть до пробела; в правой
94
части команды на нее выполняется ссылка с помощью "\1".
Вторая пара \(...\) обозначает то, что стоит после запятой и
любого количества пробелов, а ссылка на нее выполняется с
помощью "\2".
6.14.5. Маркеры
Редактор ed позволяет пометить строку некоторым именем,
чтобы впоследствии обращаться к ней по этому имени
независимо от фактического номера строки. Это удобно при
перемещении строк и отслеживании их по мере перемещения. Для
маркировки используется команда назначения имени. Если
ввести команду "kx", то текущая строка будет отмечена
маркером с именем "x". Если перед "k" указывается номер
строки, будет отмечена соответствующая строка. (Имя должно
представлять собой одну строчную букву латинского алфавита).
После этого можно ссылаться на отмеченную строку с помощью
адреса "'x".
Пример.
Пусть после создания файла были выполнены следующие
команды:
a
Первая строка вводимого текста
Вторая строка
Третья строка
Последняя строка
.
-3
ka
2
kb
$
'a, 'bm
в результате будет получена следующая последовательность
строк:
Третья строка
Последняя строка
Первая строка вводимого текста
Вторая строка
6.14.6. Адресация строк в редакторе
6.14.6.1. Адресная арифметика
Рассмотрим использование указателей строк вида ".",
"$", "/.../" и "?...?" в сочетании с действиями "+" и "-".
Так, команда:
$-1
выдает предпоследнюю строку текущего файла.
Команда:
$-5, $p
распечатывает последние шесть строк. Если в файле
нет шести строк, будет выдано сообщение об ошибке
("?").
Команда:
95
.-3, .+3p
распечатывает 7 строк, из них три строки до и три
строки после текущей строки. Знак "+" может быть
опущен. Знак "-" сам по себе представляет собой
команду для возврата на одну строку в файле.
Команда:
---
вызывает возврат на три строки, как и команда "-3".
Команда:
-, .s/bad/good/
вызывает замену "bad" на "good" в текущей и пред-
шествующей ей строках.
Знаки "+" и "-" могут использоваться при поиске с
помощью "/.../", "?...?" и с "$". По команде:
/текст/--
разыскивается строка, содержащая "текст", после чего текущей
строкой становится строка вторая перед найденной строкой.
6.14.6.2. Номера строк и указатель текущей
строки
Разрешается определять диапазон "n,m" (от строки с
номером "n" до строки с номером "m"), где "n" - номер
начальной строки, а "m" - номер конечной строки. Весь файл
целиком с первой до последней строки задается диапазоном "1,
$". Так, команда:
1, $p
вызывает выдачу всех строк файла.
Если известны номера строк, можно получить результат
выполнения команды в любой части файла.
Пример.
Команда:
5p
устанавливает указатель текущей записи на пятую
строку.
В любой момент времени можно определить, каков текущий
номер строки. Это делается с помощью команды ".=".
Использование этой команды полезно после внесения
многочисленных изменений в файл.
Можно указать несколько строк, задав диапазон "от, до".
Указатель текущей строки "." можно использовать на месте
начальной или конечной строки диапазона. Так, команда:
., $p
печатает все строки от текущей до конца файла.
6.14.6.3. Изменение указателя текущей строки
При использовании команд поиска просмотр всегда
начинается с текущей строки и продолжается в прямом или
обратном направлении до тех пор, пока не будет обнаружена
строка с искомым текстом. Например, если буфер содержит
строки:
.
АБ
.
.
БВ
.
96
и, если текущая строка - первая, то команда:
/А/, /Б/p
не распечатает строки, расположенные в промежутке от строки
"АБ" до строки "БВ", так как при использовании запятой в
качестве разделителя указателей строк, номер текущей строки
не изменяется после обработки каждого адреса, каждый поиск
начинается от текущей строки. В результате будет распечатана
одна строка "АБ".
При указании диапазона адресов вместо запятой
используется точка с запятой. Символ ";" вызывает установку
в то место, которое определяется при вычислении номеров
строк. Фактически редактор "перемещает" указатель текущей
строки. Команда:
/А/; /Б/p
распечатывает строки в диапазоне от "АБ" до "БВ", т.к. после
нахождения строки с "А" эта строка становится текущей и
поиск "Б" начинается после этой строки.
6.14.6.4. Прерывание работы редактора
Если во время выполнения команды была нажата клавиша
прерывания, будет восстановлено состояние, максимально
приближающееся к тому, которое было перед началом выполнения
команды. Естественно, некоторые изменения являются
бесповоротными: если в этот момент читался или записывался
файл, выполнялась подстановка или удаление строки, эти
команды будут остановлены в некотором промежуточном
(непредсказуемом) состоянии, указатель текущей строки
изменится.
Более определенно прерывается команда печати. Положение
указателя текущей строки не изменяется до тех пор, пока
печать не завершится. Таким образом, если запущена команда
печати и она не напечатала нужную строку, при нажатии
клавиши прерывания текущей строкой останется та строка,
которая была в момент запуска команды "p".
6.14.7. Глобальные команды
Глобальные команды используются для поиска и
редактирования тех строк в буфере редактора, которые
содержат или наоборот не содержат заданный образец.
Глобальная команда в строке должна быть первой, затем
идет образец и команды редактора. Допускается написание
нескольких команд редактора, но в этом случае каждая команда
должна располагаться на отдельной строке, и каждая строка,
за исключением последней, должна заканчиваться символом "\".
6.14.7.1. Команда g
Используется для выполнения одной или нескольких команд
редактора над всеми строками, которые содержат заданный
образец.
Общий вид командной строки (строк) с использованием
команды "g" следующий:
g/образец/ команда или перечень команд
Примеры.
g/abdc/p
97
печать всех строк буфера, содержащих последова-
тельность "abdc";
g/abcd/s//efjc/gp
замена и печать всех строк буфера, в которых
найдена последовательность "abcd";
1, $s/abcd/efjc/gp
замена во всех строках последовательности "abcd"
на "efjc" и печать последней заменяемой строки;
g/xxx/.-1s/abc/def/\
.+2s/ghi/jkl/\
.-2, .p
замена в строках до и после каждой строки, со-
держащей "xxx", и печать всех трех строк.
6.14.7.2. Команда v
Команда "v" аналогична команде "g" за исключением того,
что она работает с теми строками, которые не содержат
заданный образец.
Общий вид командной строки (строк) при использовании
команды "v":
v/образец/ команда или перечень команд
Пример.
v/xxx/s/aaa/bbb/
заменить во всех строках файла последователь-
ность "aaa" на "bbb" кроме строк, в которых
имеется последовательность "xxx".
6.15. Работа с файлами
6.15.1. Команда указания имени файла (f)
Данная команда предназначена для запроса или изменения
сохраняемого редактором имени файла (текущего имени).
Формат команды:
f [файл]
В ответ на команду "f" без агрумента редактор
напечатает сохраненное им ранее имя файла (текущее).
Это имя запоминается редактором при вызове по команде
shell:
ed file
или по команде редактора:
e file
Например, в результате выполнения команды:
f file1
имя файла, хранимое редактором, будет заменено на новое имя
"file1", и оно станет текущим.
Команда записи "w" без аргументов копирует буфер
редактора в файл с текущим именем.
Пример создания двух вариантов файла "file1":
ed file1
f file2
...
w
w file3
q
98
6.15.2. Объединение файлов
Предположим, что в файле "file1" сразу же после слов
"текст..." требуется вставить "file2".
Для этого необходимо вызвать редактор для фала "file1",
найти символы "текст..." и добавить в это место файл
"file2":
ed file1
/текст.../
текст... (ответ редактора)
.r file2
Команда "r" без адресов добавляет читаемые строки в
конец, т.е. работает аналогично "$r".
6.15.3. Разбиение файла
Предположим, что нужно выделить в отдельный файл
некоторую таблицу, чтобы ее можно было отдельно
форматировать и проверять.
.TS
... (содержимое)
.TE
Для выделения этой таблицы в отдельный файл с именем
"table" в первую очередь нужно найти начало этой таблицы
(строку "TS"), а затем записать соответствующий фрагмент в
файл:
/^\.TS
.TS (редактор печатает найденную строку)
.,/^\.TE/w table
В результате этого поставленная цель будет достигнута.
Можно выполнить все это и в одной команде:
/^\.TS/;/^\.TE/w table
Дело в том, что команда "w" может выполнять запись не
всего файла, а некоторой группы строк. При желании можно
записать даже одну строку, для этого надо задать один номер
строки вместо двух.
6.15.4. Перекомпоновка файла
6.15.4.1. Перемещение строк (команда m)
Данная команда предназначена для перемещения строк в
буфере редактора.
Формат команды:
[n[, k]]ml
где n, k - номера начальной и конечной перемещаемых
строк;
m - команда перемещения;
l - номер строки, после которой надо поместить
строки с номерами от "n" до "k" включительно.
По данной команде строки с номерами от "n" до "k"
включительно помещаются после строки с номером "l", причем
на прежнем месте эти строки не сохраняются.
Пример.
1, 3m$
99
группу строк с 1-й по 3-ю поместить после
последней строки в буфере редактора.
Если указан один номер строки, то перемещается только
эта строка.
Если номер отсутствует, то перемещается текущая строка.
Данная команда может успешно использоваться вместе с
командой поиска.
Например, имеется следующий текст:
ПЕРВЫЙ ПАРАГРАФ
(текст)
КОНЕЦ ПЕРВОГО ПАРАГРАФА
ВТОРОЙ ПАРАГРАФ
(текст)
КОНЕЦ ВТОРОГО ПАРАГРАФА
Если необходимо переставить параграфы местами, то это
можно выполнить с помощью команды:
/ВТОРОЙ/, /КОНЕЦ ВТОРОГО/m/ПЕРВЫЙ/-1
Строки, начиная со строки, содержащей слово "ВТОРОЙ",
до строки, содержащей слова "КОНЕЦ ВТОРОГО" включительно,
помещаются перед строкой, содержащей слово "ПЕРВЫЙ".
По завершинию операции перемещения текущей строкой
становится последняя перемещенная строка (в последнем
примере - это строка со словами "КОНЕЦ ВТОРОГО").
6.15.4.2. Копирование строк текста (t)
Команда копирования "t" аналогична команде "m", за
исключением того, что блок текста не удаляется, а копия
этого блока помещается после указанной строки текста.
Формат команды:
[n[, k]]tl
где n, k - номера начальной и конечной копируемых
строк; если указано только n, то копируется
одна строка с номером n; если номер строки
не указан, то копируется текущая строка;
t - команда копирования;
l - номер строки, после которой надо поместить
строки с номерами от "n" до "k" включительно.
В следующем примере показано, как поместить 3 строки
ниже последней строки. Экран выглядит следующим образом:
Пример.
5, 8n
5 Close the door of the room.
6 Break glass of neareat alarm.
7 Pull lever.
8 Locate and use fire extinguishar.
30n
30 A chemical fire in the lab requires that you:
6,8t30
30, $n
30 A chemical fire in the lab requires that you:
31 Break glass of neareat alarm.
32 Pull lever.
33 Locate and use fire extinguishar.
6, 8n
6 Break glass of neareat alarm.
7 Pull lever.
8 Locate and use fire extinguishar.
Текст с 6-й по 8-ю строки остается на месте, копия этих
100
трех строк помещается после 30-й строки.
6.16. Специальные символы
Некоторые символы имеют для редактора особое значение.
К ним относятся: ".", "\", "$", "*", "[", "]", "^", "&". Эти
символы обычно называются метасимволами.
6.16.1. Метасимвол . (точка)
В зависимости от контекста символ "." имеет несколько
значений. lin В левой части команды подстановки и при поиске
с помощью конструкции "/.../" символ "." означает любой
одиночный символ. Таким образом, в результате поиска
/x.y/
будут найдены строки текста, содержащие символы "x" и "y",
между которыми находится любой символ, например:
x+y
x-y
x y
Символ ".", используемый для указания номера строки
обозначает текущую строку.
Примеры.
.+1s/a/,/
замена символа "a" на символ "," в строке, сле-
дующей за текущей. Символ ".", записанный в пра-
вой части команды замены "s", не имеет специаль-
ного значения;
1, 5s/,/./
замена символа "," на символ "." в строках с 1-й
по 5-ю включительно.
Команда :
.s/././
иллюстрирует все значения символа ".". Первая "."
в команде - это номер текущей строки, вторая "."
это метасимвол, который соответствует любому
одному символу данной строки, третья "." - это
настоящая точка в команде замены.
Такая команда, примененная, например к строке:
ОШИБКА ЧТЕНИЯ.
дает результат:
ОШИБКА ЧТЕНИЯ.
6.16.2. Метасимвол \ (обратная дробная черта)
Обратная дробная черта (или обратный слэш) отменяет
специальное значение, которое может иметь следующий за ней
символ, в частности, "\." означает точку, а не "любой
символ".
Примеры.
s/\./?/
замена символа "." на символ "?";
/\.pp/
поиск строк, содержащих ".pp";
/\/
поиск символа "\";
/\//
101
поиск символа "/";
s/\\\.//
удаление в текущей строке последовательности
символов ".".
Для разделения полей в команде "s" может использоваться
любой символ, а не только дробная черта (однако для
контекстного поиска требуется использовать дробную черту).
Например, если строка уже содержит много символов дробной
черты, как в строке:
//exec//sys.fort.go //etc ...
то можно использовать в качестве разделителей символ ":"
(двоеточие). Удалить все символы дробной черты можно с
помощью команды:
s:/::g
Если для стирания символов и удаления строк
используются клавиши "#" и "@", их нужно вводить в виде "\#"
и "\@" (это относится не только к работе с ed).
Если текст вводится с помощью одной из команд: "a", "i"
или "c", то символ обратной дробной черты не является
специальным, и требуется нажимать эту клавишу только один
раз для каждой обратной дробной черты.
6.16.3. Метасимвол $ (денежный знак)
В зависимости от того, как используется знак денежной
единицы ($), он может обозначать конец файла или конец
строки. Когда указывается диапазон (от строки 1 до строки
$), совершенно ясно, что речь идет о конце файла. "1, $p"
вызовет распечатку всего файла. Но запись "s/$/./p"
указывает, что точка будет помещена в конце текущей строки.
В команде:
$s/$/$
первый символ "$" означает последнюю строку файла, второй -
означает конец этой строки, а третий действительно является
символом денежной единицы, который добавляется к указанной
строке.
6.16.4. Метасимвол ^ (отрицание)
Метасимвол "^" применяется так же, как метасимвол "$",
за исключением того, что он указывает начало строки, а не
конец.
Примеры.
/^время/
поиск строки, начинающейся со слова "время";
s/^/ /
поместить пробел в начало текущей строки.
Метасимволы можно объединять. Например, для того, чтобы
найти строку, содержащую только символы "pp" можно
использовать команду:
/^.pp$/
6.16.5. Метасимвол * (звездочка)
Метасимвол "*" означает, что символ, за которым он
следует, может повторяться произвольное число раз.
Если в тексте имеется большое количество пробелов, их
102
можно сжать, например:
Московское время 18 часов
В результате выполнения команды:
s/e *время 1/e время 1/p
получим:
Московское время 18 часов
Если скомбинировать точку и *, то можно сопоставить все
символы. С помощью этой комбинации можно, например, заменить
все символы в последней части строки:
p
Toads are alimy, cold creatures
s/are.*/are wonderful and warm
Toads are wonderful and warm
ed автоматически запоминает последнюю строку символов в
шаблоне поиска или замененный текст. Однако вы должны
подсказать ed, что нужно повторить замену, используя знак
"%". Знак "%" позволяет вам сделать одинаковую замену во
многих строках, не используя глобальной замены. Например,
заменим слово money на слово gold, повторим последнюю замену
в строках от 1 до 3:
1, $n
1 I love money
2 I need food
3 I use money
4 The IRS wants my money
ls/money/gold
I love gold
3s//g
I use gold
1, $n
1 I love gold
2 I need food
3 I use gold
4 The IRS wants my money
ed автоматически запоминает слово money, так что строка
не будет повторена между первыми двумя ограничителями. Знак
"%" говорит ed - использовать последний шаблон для замены
(gold).
6.16.6. Метасимволы [] (квадратные скобки)
Метасимволы "[]" позволяют определить подмножество
символов, которые необходимо распознавать при выполнении
операции поиска или подстановки. Запись группы символов,
заключенных в квадратные скобки, означает: "любой одиночный
символ из указанных". Например, если "[0123456789]", это
будет означать: "любая цифра". Можно записать и короче:
"[0-9]". Запись двух символов, разделенных знаком минус,
означает задание интервала в лексикографической
последовательности символов. Так, запись "[А-Я]" означает:
"прописная русская буква", а запись: "[a-z] [a-z0-9]*"
означает последовательность латинских букв и цифр,
начинающуюся с буквы.
Указание в начале класса символа "^" означает "ни один
из следующих символов". Например:
^[0-9]
обозначает "любой символ, за исключением цифры".
Примеры.
1, $s/^[0-9]*//
103
удаление всех цифр в начале каждой строки;
/^[^(пробел)(табуляция)]/
поиск первой строки, не начинающейся символом
пробела или табуляции.
Внутри класса символов могут присутствовать любые
символы и, чтобы избежать путаницы, в квадратных скобках
символы принципиально не имеют специального значения.
Например, чтобы найти специальные символы, можно
использовать команду:
/[.[]/
Внутри "[...]" символ "[" не является специальным. Чтобы
включить символ "]" в класс символов, нужно указать его
первым.
6.16.7. Метасимвол & (амперсенд)
Символ "&" используется в первую очередь для сокращения
вводимого текста.
Предположим, имеется строка:
В ЭТО ВРЕМЯ
и требуется преобразовать ее в строку:
В ЭТО ВРЕМЯ СУТОК
конечно, для этого можно воспользоваться командой:
s/ВРЕМЯ/ВРЕМЯ СУТОК/
однако требование повторно указывать слово "ВРЕМЯ" кажется
неразумным. Для того, чтобы избежать этого повторения,
используется символ "&". В правой части команды подстановки
амперсенд означает "найденный текст", так что можно ввести
команду:
s/ВРЕМЯ/& СУТОК/
где "&" будет означать "ВРЕМЯ". Конечно, в данном примере
экономия будет незначительной, однако если количество
символов велико или представляет собой нечто вроде ".*",
которому соответствует большой кусок текста, экономится
много вводимых символов. Снижается также вероятность
совершения ошибки при вводе заменяющего текста. Например,
для того, чтобы заключить в скобки строку, независимо от ее
длины, можно использовать команду:
s/.*/(&)/
Амперсенд может встречаться в правой части команды
несколько раз. Команда:
s/ВРЕМЯ/& СУТОК И & ГОДА/
построит строку:
ВРЕМЯ СУТОК И ВРЕМЯ ГОДА
а команда:
s/В ЭТО ВРЕМЯ/&? &!!!/
преобразует исходную строку в:
В ЭТО ВРЕМЯ? В ЭТО ВРЕМЯ!!!
Чтобы получить настоящий символ "&", используется
обратная дробная черта для отмены его специального значения.
Команда:
s/амперсенд/\&/
заменит слово "амперсенд" на символ "&". Обратите внимание
на то, что символ "&" является специальным только в правой
части команды, в левой части он не имеет специального
значения.
6.17. Дополнительные возможности
104
6.17.1. Временный выход из редактора
Иногда бывает удобно на некоторое время выйти из
редактора, для выполнения какой-либо другой команды, не
покидая редактор. Это можно сделать с помощью команды
временного выхода "!".
Если ввести:
!команда_системы
процесс редактирования приостанавливается и выполняется
указанная команда. Редактор сообщает о завершении этой
команды, печатая еще один восклицательный знак "!", после
этого можно снова возобновлять редактирование.
6.17.2. Восстановление после останова
Если произойдет неожиданный останов, система UNIX
пытается сохранить содержимое буфера редактора в специальном
файле ed.hup. Позднее вы можете попытаться восстановить
текст из этого файла одним из двух способов. Первый: вы
можете воспользоваться командой shell, чтобы переписать файл
ed.hup в файл с другим именем. Второй: вы можете войти в
редактор ed и воспользоваться командой f для переименования
в буфере:
ed ed.hup
928
f myfile
myfile
6.17.3. Командные файлы редактора
Если достаточно сложный набор операций редактирования
должен быть выполнен над многими файлами, это проще всего
сделать путем создания командного файла редактора,
содержащего нужные операции, и последующего применения этого
командного файла поочередно ко всем файлам.
Предположим, например, что нужно заменить каждое слово
"версия1" на "версия2" и каждое слово "1985" на "1986" в
большом количестве файлов. Поместим в файл "list" следующий
строки:
g/версия1/s//версия2/g
g/1985/s//1986/g
w
q
после этого можно воспользоваться командами:
ed file1 < list
ed file2 < list
...
Это приведет к тому, что редактор ed будет получать
команды из ранее приготовленного файла. В этом случае вся
работа должна планироваться заранее.
С помощью интерпретатора команд системы можно более или
менее легко просмотреть набор файлов циклически.
6.17.4. Режим шифрования
При обработке зашифрованных файлов, редактор вызывается
с параметром "-x":
105
ed -x имя_файла
В этом случае перед началом копирования файла
запрашивается ключ, по которому производится шифрование и
расшифровка информации при всех обменах с файлом.
Переход в режим шифрования возможен и в процессе
сеанса. С этой целью пользователь может установить текущий
ключ с помощью команды:
x
После чего будет выдана подсказка:
Entering encrypting mode!
Key:
и пользователь набирает ключ (при этом символы не
отображаются на экране терминала). Признаком окончания ввода
ключа является ввод . Ввод ключа нулевой длины отменят
режим шифрования.
6.17.5. Программа grep
Иногда требуется найти случаи употребления некоторого
слова или образца в ряде файлов для того, чтобы
отредактировать их или просто проверить наличие или
отсутствие. Можно отредактировать каждый файл в отдельности
и отыскать там представляющий интерес образец, однако, если
файлов много, это может оказаться достаточно утомительным, а
если файлы очень велики, то просто невозможным из-за
ограничения редактора ed.
Программа grep языка управления заданиями предназначена
для печати всех строк, соответствующих указанному образцу.
Так, команда:
grep "нечто" файл1 файл2 файл3 ...
находит "нечто" везде, где оно встречается в файлах. Команда
"grep" указывает также файл, в котором была найдена каждая
строка и (если задан параметр "-n") номер строки.
Образец, обозначенный "нечто", может быть любым
образцом, который вы используете в редакторе, т.к. grep и ed
используют один и тот же механизм поиска образцов. Если
образец содержит какие-либо неалфавитные символы, его
целесообразно всегда заключать в апострофы ('...'),
поскольку многие такие символы имеют специальное значение
для интерпретатора команд shell. Если не поместить их в
апострофы, интерпретатор команд попытается обработать их
перед тем, как они будут переданы команде grep.
Существует также возможность находить строки, которые
не содержат указанного образца. Команда:
grep -v "нечто" файл1 файл2 ...
находит все строки, которые не содержат "нечто". Ключ "-v"
должен находиться в указанной позиции. С помощью команд
"grep" и "grep -v" можно выбирать строки, содержащие
некоторую комбинацию образцов. Например, для получения всех
строк, содержащих "x", но не содержащих "y", можно
использовать команду:
grep x файл ... | grep -v y
(символ "|" означает, что результат работы первой команды
используется в качестве входа второй команды).
6.17.6. Команды помощи
Обратите внимание, что когда вы редактируете файл,
106
редактор ed иногда в ответ на введенную вами команду
отвечает знаком "?". Знак "?" означает диагностическое
сообщение при обнаружении ошибки. Команды помощи выдают вам
короткое сообщение, объясняющее причину ошибки. Существуют
две команды помощи:
h - отображает короткое сообщение об ошибке;
H - устанавливает в ed режим распечатки короткого сообщения
об ошибке каждый раз, когда появляется "?". Для отмены
этого режима вновь введите H.
Если попытаться завершить работу с ed, не записав
измененный буфер в файл, то появится знак "?". Когда
появится "?", введите "h":
q
?
h
warning: expecting "w"
6.18. Сообщения редактора
Диагностические сообщения, выдаваемые редактором в
процессе работы, крайне лаконичны, это:
WRITE ERROR - ошибка записи, связанная либо с отсутствием
места на устройстве, либо со сбоем аппаратуры;
Entering encrypting mode! - свидетельствует о включении
режима шифрования;
MEM? - выдается в режиме дозаписи в буфер редактора при
достижении предельного размера буфера;
?(file) - при начале работы или после команд "e", "r", "f"
означает, что указанный файл (file) отсутствует; после
команды "w" - означает, что запись в файл запрещена.
Если при вводе команды зарегистрирована какая-либо
другая ошибка, редактор сообщит об этом, выдав символ "?".
6.19. Краткий обзор команд
В общем случае команды редактора ed состоят из имени
команды, которому могут предшествовать один или два номера
строк, и после которого для команд "e", "r" и "w" может
указываться имя файла. В строке может присутствовать только
одна команда, однако команда "p" может следовать после любой
другой команды, кроме "e", "r", "w" и "q".
a - Дописать строки в буфер редактора после текущей строки,
(если не задана другая строка). Дозапись продолжается
до тех пор, пока не будет введена команда ".".
Текущей становится последняя дописанная строка. В этой
команде допускается адрес "0", при этом текст
помещается в начало буфера.
c - Заменить указанные строки новым текстом, следующим после
команды "c". Ввод новых строк завершается ".". Если
номера строк в команде не указаны, заменяется текущая
строка. Текущей становится последняя замененная строка
или (если строк замены не было) строка, предшествующая
удаленным строкам.
d - Удалить указанные строки. Если номера строк не заданы,
удаляется текущая строка. Текущей становится первая
неудаленная строка, кроме случая, когда удаляется
последняя строка буфера. В этом случае текущей
становится новая последняя строка буфера.
107
e - Релактирование нового файла. Предшествующее содержимое
буфера теряется, так что предварительно полезно ввести
команду "w". Текущей становится последняя строка
буфера.
E - Команда выполняет те же действия, что и "e", за
исключением того, что не выдается сообщение, если после
последнего изменения буфера не была выдана команда
записи "w".
f - Выдать текущее имя файла. Если после команды "f"
указывается имя файла, текущее имя файла будет заменено
этим именем.
g - Конструкция "g/re/команды" выполняет указанные "команды"
над теми строками, которые соответствуют образцу "re".
i - Вставить строки перед указанной строкой (или строкой,
определяемой точкой). Вставка завершается командой
".". Текущей становится последняя вставленная
строка.
j - Объединить указанные строки в одну строку. Если строки
не указаны, объединяются текущая и следующая за ней
строки.
k - Отметить строку (указанную или текущую) маркером,
задаваемым псле "k". В качестве маркера используются
строчные латинские буквы.
l - Распечатать строки. Команда "l" эквивалентна команде
"p", однако она распечатывает графически не
отображаемые символы и "сворачивает длинные строки".
m - Поместить указанные строки после строки, задаваемой
после "m". Текущей становится последняя перемещенная
строка.
p - Выдать указанные строки. Если строки не указаны,
распечатывается текущая строка. Отдельный номер строки
эквивалентен команде "(номер_строки)p". Простое нажатие
клавиши распечатывает следующую строку.
q - Выход из редактора. Если при этой операции теряется
информация (например, копия исходного файла изменялась,
но не была выдана команда записи "w"), после первой
команды "q" выдается подсказка "?" и никаких действий
не производится. Выдача подряд двух команд "q" без
предварительной команды "w" приводит к стиранию буфера
и окончанию работы с редактором.
Q - Работает также как команда "q" за исключением того, что
выход производится немедленно (без какой-либо
диагностики о возможной потере информации).
r - Прочитать файл в буфер (в конец буфера, если не указано
по-другому). Текущей становится последняя считанная
строка.
s - Команда s/xxx/yyy/ подставляет вместо символов "xxx"
символы "yyy" в указанных строках. Если строки не
указаны, подстановка выполняется в текущей строке.
Текущей становится последняя строка, в которой
произошла подстановка, это приводит к сохранению
исходного положения, если не была выполнена ни одна
подстановка. Команда "s" заменяет только первое
вхождение "xxx" в строке. Для замены всех вхождений
после завершающей дробной черты указывается символ "g".
t - Скопировать указанные строки после строки, задаваемой
после "t". Текущей становится последняя скопированная
строка.
108
u - Аннулировать изменение, выполненное предшествующей
командой.
v - Конструкция "v/re/команды" выполняет указанные "команды"
над теми строками, которые не соответствуют образцу
"re".
w - Записать буфер в файл. Значение указателя текущей строки
не изменяется.
W - Аналогична команде "w", за исключением того, что
указанные строки дописываются к файлу.
x - Работа в режиме шифрации. Запрашивается ключ, используя
который последующие команды "r", "е" и "w" будут
зашифровывать и расшифровывать текст. Пустой ключ
отменяет режим шифрации.
.= - Выдать текущий номер строки (один символ "=" печатает
номер последней строки).
! - Конструкция "!командная_строка" вызывает выполнение
"командной_строки" интерпретатором команд.
/re/ - Контекстный поиск. Поиск следующей строки, которая
содержит данную последовательность символов, и ее
выдача. Текущей становится строка, соответствующая
заданному образцу "re". Поиск начинается со строки
".+1" до "$", после последней строки переходит к строке
1 и, при необходимости, продолжается до текущей строки.
?re? - Контекстный поиск в обратном направлении. Поиск
начинается со строки 1 и продолжается до последней
строки.
. (точка) - Обозначение текущей строки.
$ - Обозначение последней строки.
'x - Обозначение строки, ранее отмеченной маркером "x".