Книга: UNIX — универсальная среда программирования

Приложение 1 Краткое описание редактора

Приложение 1

Краткое описание редактора

Стандартный текстовый редактор UNIX создан К. Томпсоном в начале 70-х годов для вычислительной среды на малых машинах (первая система UNIX ограничивала предельный размер программ пользователя до 8К байт) с терминалами "твердой копии", работавшими при очень низких скоростях (10-15 символов в секунду). Этот редактор написан на базе более ранней версии qed, которая была в то время популярна.

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

Почему же тогда мы тратим время на, казалось бы, устаревшую программу? Дело в том, что ed выполняет некоторые операции весьма успешно, несмотря на свой возраст. Эта программа есть на всех установках UNIX, и вы всегда найдете ее при переходе с одной системы на другую. Она работает хорошо и с низкоскоростными телефонными линиями, и с любыми терминалами. Кроме того, ed легко запускать из командного файла, в то время как большинство экранных редакторов управляются с терминала и не могут должным образом получить входной поток из файла.

Редактор ed предоставляет регулярные выражения для поиска по образцу. Регулярные выражения, на которых основан ed, присутствуют во всех частях системы: grep и sed применяют почти такие же, a egrep, awk, lex расширяют их. Shell использует для сравнения имен файлов иной синтаксис, но те же самые идеи. Некоторые экранные редакторы имеют "строчный режим", который предусматривает обращение к регулярным выражениям ed.

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

Основные сведения

Программа ed редактирует один файл за один раз. Она работает с копией файла. Чтобы внести исправления в первоначальный файл, вы должны дать явную команду. Редактор предоставляет команды для манипуляций с последовательными строками или строками, соответствующими образцу, а также команды для внесения в строки изменений.

Каждая команда ed представляет собой символ (обычно букву). Большинству команд может предшествовать один или два номера строки, которые указывают, на какую строку или строки должна воздействовать команда: в противном случае подразумевается номер, принятый по умолчанию. Номер строки можно специфицировать абсолютной позицией в файле (1, 2 ...), символами $ для последней строки и "." для текущей, процедурой поиска по образцу, использующей регулярные выражения, и их аддитивными комбинациями.

Рассмотрим, как с помощью ed можно создавать файлы, используя стихи Де Моргана из первой главы.

$ ed poem
? poem
Предупреждение: файл poem не существует

а      Начать добавление строк

Great fleas have little fleas
 upon their backs to bite 'em,
And little fleas have lesser fleas,
 and so ad infinitum.
.      
Печатаем '.' чтобы закончить ввод

w poem Пишем строки в файл poem

121    ed сообщает, что записан 121 символ

q      Выход

Команда а добавляет или присоединяет строки. Режим добавления заканчивается строкой, состоящей из одной точки. Из-за отсутствия индикации режима, в котором вы работаете, возможны две распространенные ошибки: ввод текста без команды а и ввод команды до ввода '.'.

Редактор ed никогда не будет писать ваш текст в файл автоматически; вы должны задать это с помощью команды w. Однако, если вы пытаетесь закончить редактирование без записи ваших изменений, ed выдает '?' как предупреждение. Есть другая команда q, позволяющая завершить работу независимо от внесения исправлений.

$ ed poem
121      
Файл существует и имеет 121 символ

а         Добавить еще строки в его конец

And the great fleas themselfs, in turn,
 have greater fleas to go on;
While these again have greater still,
 and greater still, and so on.
.        
Печатаем '.' для завершения

q         Пытаемся выйти

?         Предупреждение: не было записи

w         Нет имени файла; подразумевается poem

263
q        
Теперь можно выходить

$ wc poem Проверьте для уверенности

8 46 263 poem
$

Временная передача управления shell с помощью '!'

Если вы запустили ed, то можете временно выйти из него, чтобы запустить другую команду shell. В этом случае нет необходимости прекращать работу достаточно ввести команду ed '!'.

$ ed poem
! wc poem
Запуск wc без выхода из ed

8 46 263 poem
!         
Вернулись из команды

q         Выход без w годится: не было исправлений

$

Печать

Строки файла нумеруются как 1, 2 … Вы можете печатать n-ю строку, дав команду np или просто номер n, и строки с m по n, используя m,np. "Номером строки" $ обозначается последняя строка, так что строки можно не считать.

1 Печатать первую строку; то же самое
$ Печатать последнюю строку; $p то же самое
1,$p Печатать строки с первой по последнюю

Печатать файл по одной строке проще всего; нажимая клавишу RETURN, вы можете вернуться на одну строку назад с помощью '-'. Можно комбинировать номера строк с '+' и '-'.

$-2,$p Печатать последние три строки
1,2+3p Печатать строки с первой по пятую

Однако нельзя печатать после конца файла или в обратном порядке; команды типа $,$+1p и $,1p считаются незаконными.

Команда list 1 выводит текст в формате с видимыми символами. Это удобно при поиске в файлах управляющих символов, при различении пробелов, табуляции и т.п. (см. vis в гл. 7).

Образцы

Как только размер начинает превышать две строки, становится неудобным печатать его весь целиком, чтобы отыскать нужную строку. Редактор ed предлагает способ поиска строк, совпадающих с некоторым образцом, шаблоном: /pattern/ обнаруживает очередное вхождение pattern.

$ ed poem 263
/flea/
Ищет очередную строку, содержащую flea

Great fleas have little fleas
/flea/
Ищет еще одну

And little fleas have lesser fleas,
//    
Ищет следующую по тому же образцу

And the great fleas themselves, in turn,
??    
Поиск в обратном направлении по тому же образцу

And little fleas have lesser fleas,

Редактор запоминает образец, применявшийся вами в последний раз, так что можно повторить поиск просто с помощью //. Для поиска в обратном направлении воспользуйтесь ?pattern? и ??.

Поиск с помощью /.../ и ?...? циклический, т.е. продолжается в обратном направлении после достижения одного из концов текста:

$p     Печатать последнюю строку ('p' необязательна)

and greater still, and so on.
/flea/
Следующее flea вблизи начала

Great fleas have little fleas
??    
От начала идет в обратном направлении

 have greater fleas to go on;

Результатом поиска по образцу типа /flea/ является номер строки, например 1 или $, который может использоваться в том же контексте, что и такие номера:

1,/flea/p Печатать от единицы до следующего flea
?flea?+1,$p Печатать от предыдущего flea + 1 до конца

Текущая редактируемая строка. Редактор ed отслеживает последнюю строку, с которой имели дело: печатали или вводили текст, читали из файла. Это текущая строка с именем '.'. Каждая команда определенным образом влияет на текущую строку, обычно настраивая ее на ту, с которой она последний раз работала. Вы можете использовать текущую строку так же, как $ или номер строки типа 1:

$ ed poem
263
.     
Печатает текущую строку; после чтения файла

это то же, что $

 and greater still, and so on.
.-1,.p
Печатает предыдущую строку и еще одну

While these again have greater still,
 and greater still, and so on.

Выражения для номера строки могут быть сокращены:

Сокращение Эквивалент Сокращение Эквивалент
-1 .-1 + .+1
-- или -2 .-2 ++ или +2 .+2
-n .-n +n .+n
$- $-1 .3 .+3

Добавление, замена, исключение, вставка

Команда а (добавить) добавляет строки после определенной строки, команда d (удалить) вычеркивает строки, команда i (вставить) вставляет строки перед определенной строкой, команда с (заменить) заменяет строки, действуя как комбинация команд "удалить" и "вставить".

na Добавить текст после строки n
ni Вставить текст перед строкой n
m,nd Удалить строки с m по n
m,nc Заменить строки с m по n

Если номера строк не указаны, используется текущая строка. Новый текст для команд а, с и i оканчивается строкой '.'; точка, введенная в последней строке, оставляется. Текущая строка настраивается на следующую строку после последней удаленной, за исключением случая, когда удалена последняя строка, т.е. $.

Добавить текст в начало (то же, что 1i)
dp Удалить текущую строку, печатать следующую (или последнюю, если $)
.,$dp Удалить отсюда до конца, печатать новую последнюю
1,$d Удалить все
?pat?,.-1d Удалить от предыдущей, совпадающей с 'pat' до той, что перед текущей
$dp Удалить последнюю строку, печатать новую последнюю
$c Заменить последнюю строку ($а добавляет после последней строки)
1,$c Заменить все строки

Подстановка, аннулирование

Нет необходимости перепечатывать целую строку, если в ней нужно заменить лишь несколько символов. Команда подстановки s заменяет одну последовательность символов другой:

s/old/new/ Заменить первую old на new в текущей строке
s/old/new/p Заменить первую old на new и печатать строку
s/old/new/g Заменить каждую old на new в текущей строке
s/old/new/gp Заменить каждую old на new и печатать строку

Заменяется только самое левое вхождение образца в строке, если не написана буква 'g'. Команда s выводит измененную строку только в том случае, когда она оканчивается буквой 'p'. Фактически большинство команд ed выполняет свою работу "молча", но почти любая команда может быть завершена буквой p для вывода результата.

Если подстановкой вы не добились того, что хотели, с помощью команды u (аннулировать) можно уничтожить последнюю подстановку. Текущая строка должна быть настроена на преобразованную строку:

u Аннулировать последнюю сделанную подстановку
up Аннулировать последнюю подстановку и напечатать

Как вам уже известно, командам p и d могут предшествовать один или два номера, указывающие строки, на которые нужно воздействовать. Этот же принцип используется и для команды s.

/old/s/old/new/ Найти следующую old; заменить на new
/old/s//new Найти следующую old; заменить на new (образец запоминается)
1 ,$s/old/new/p Заменить первую old на new в каждой строке; печатать последнюю измененную строку
1,$s/old/new/gp Заменить каждую old на new в каждой строке; печатать последнюю измененную строку

Отметим, что 1,$s вызывает команду для обработки каждой строки, но это означает лишь самое левое вхождение образца в каждой строке; нужна заключительная команда 'g', чтобы заместить все вхождения во всех строках. Кроме того, p выдает только последнюю измененную строку. Для вывода всех измененных строк необходима глобальная команда, которую мы вскоре рассмотрим.

Символ & означает сокращение; оказавшись где либо справа от команды s, он заменяется образцом из левой части:

s/big/very &/ Заменить big на very big
s/big/& &/ Заменить big на big big
s/.*/(&)/ Взять в скобки целую строку (см. .* ниже)
s/and/&/ Заменить and на & ( отключает специальное значение символа)

Метасимволы и регулярные выражения

Как и символы *, >, :, имеющие специальный смысл в shell, некоторые символы имеют специальный смысл для ed, если они появляются в образце для поиска или в левой части команды s. Эти символы называют метасимволами, а использующие их образцы регулярными выражениями. В табл. П.1.1 перечислены все символы и их значения. Примеры, приведенные ниже, следует читать в соответствии с таблицей. Специальный смысл любого символа может быть отменен предшествующей ему обратной дробной чертой ''.

с Любой специальный символ задает совпадение с таким же символом
c Отменяет специальный смысл символа с
А Соответствует началу строки, когда ^ начинает образец
$ Соответствует концу строки, когда $ заканчивает образец
. Совпадает с любым одиночным символом
[...] Соответствует одному любому символу в ...; допустимы диапазоны типа a-z
[^...] Соответствует любому одиночному символу, не входящему в ...; допустимы диапазоны
r* Соответствует нулевому или более числу вхождений r, где r символ, или [...]
& Используется только в правой части s; вставляет фрагмент, совпавший с образом
(...) Помечает регулярное выражение; найденная строка доступна как 1, и т.д. в левой и правой частях выражения

Таблица П.1.1: Регулярные выражения редактора

Символу перевода строки не соответствует ни одно регулярное выражение.

Образец Соответствие
/^$/ пустая строка, т.е. только конец строки
/./ непустая, т.е. по крайней мере один символ
/^/ все строки
/thing/ thing где либо в строке
/^thing/ thing в начале строки
/thing$/ thing в конце строки
/^thing$/ строка, состоящая лишь из thing
/thing.$/ thing плюс любой символ в конце строки
/thing.$/ thing. в конце строки
//thing// /thing/ где либо в строке
/[tT]hing/ thing или Thing где либо в строке
/thing[0-9]/ thing, за которой одна цифра
/thing[^0-9]/ thing, за которой не цифра
/thing[0-9][^0-9]/ thing, за которой цифра и не цифра
/thing1.*thing2/ thing1, затем любая строка, затем thing2
/^thing1.*thing2$/ thing1 в начале и thing2 в конце

Регулярные выражения, использующие *, выбирают самое левое совпадение с образцом до тех пор, пока это возможно. Отметим, что x* может соответствовать нулю, а xx* одному или более символу.

Глобальные команды

Глобальные команды g и v управляют вызовом одной или большего числа других команд, выполняющих преобразования в множестве строк, выбранных регулярным выражением. Команда g наиболее часто используется для печати, подстановки или удаления множества строк:

m,ng/re/cmd Для всех строк между m и n, которые соответствуют re выполнить cmd
m,nv/re/cmd Для всех строк между m и n, которые не соответствуют re выполнить cmd

Командам g и v могут предшествовать номера строк, ограничивающие диапазон; по умолчанию принимается диапазон 1,$:

g/.../p Печатать все строки, соответствующие регулярному выражению ...
g/.../d Убрать все строки соответствующие ...
g/.../s//repl/p Заменить первое вхождение ... в каждой строке на 'repl', печатать измененные строки
g/.../s//repl/gp Заменить каждое ... на 'repl' , печатать измененные строки
g/.../s/pat/repl/ В строках, соответствующих ..., заменить первую 'pat' на 'repl'
g/.../s/pat/repl/p В строках, соответствующих ..., заменить первую 'pat' на 'repl' и печатать
g/.../s/pat/repl/gp В строках, соответствующих ..., заменить все 'pat' на 'repl' и печатать
v/.../s/pat/repl/gp В строках, не соответствующих ..., заменить все 'pat' на 'repl' и печатать
v/^$/p Печатать все непустые строки
g/.../cmd1cmd2cmd3 Выполнять составные команды с единственной g, присоединить к каждой cmd кроме последней

Команды, управляемые командами g или v, также могут использовать номера строк, текущая строка настраивается по очереди на каждую выбранную строку:

g/thing/.,.+1р Печатать каждую строку с thing и следующую
g/^.EQ/.1, /^.EN/s/alpha/beta/gp Заменять alpha на beta только между .EQ и .EN и печатать измененные строки

Перемещение и копирование строк

Команда m перемещает группу смежных строк, а команда t копирует группу строк:

m,n,md Переместить строки m по n за строку d
m,n,td Скопировать строки m по n за строку d

Если исходные строки не определены, используется текущая строка. Строка назначения d не может быть в диапазоне m,n-1. Ниже приведено несколько общих идиом, включающих m и t.

m+ Поместить текущую строку после следующей (переставить)
m-2 Поместить текущую строку перед предыдущей
m-- То же самое: это то же, что -2
m- Ничего не делать
m$ Поместить текущую строку в конец (m0 — поместить в начало)
t. Дублировать текущую строку (t$ дублирует в конце)
-,.t. Дублировать предыдущую и текущую строки
1,$t$ Дублировать все множество строк
g/^/m0 Инвертировать порядок строк

Метки и номера строк

Команда = печатает номер строки $ (слабое умолчание), .= печатает номер текущей строки и т.д. Положение текущей строки не изменяется.

Команда kc метит нужную строку буквой с; впоследствии на эту строку можно ссылаться с помощью 'c. Команда k не меняет положение текущей строки. Метки удобны при перемещении больших фрагментов текста, поскольку они остаются привязанными к строкам, как показано в приведенной ниже последовательности:

/.../ka Найти строку ... и пометить буквой a
/.../kb Найти строку ... и пометить буквой b
'a,'bp Печатать целый диапазон, чтобы быть уверенным
/.../ Найти нужную строку
'а,'bm Поместить выбранные строки после нее

Объединение, расщепление и реорганизация строк

Строки могут быть объединены с помощью команды j (пробелы не добавляются):

m,nj объединяет строки с m по n в одну
jp Объединить текущую строку со следующей и печатать
-,.jp Объединить предыдущую строку с текущей и печатать

По умолчанию принимается диапазон .,.+1;

Строки можно расщепить командой подстановки, отделив новую строку:

s/part1part2/part1part2/ Расщепить строку на две части
s/ / /g Расщепить по каждому пробелу. Оставить одно слово на строку

Текущей становится последняя созданная строка.

Чтобы манипулировать не только целыми фрагментами, выбираемыми регулярными выражениями, но и их соответствующими частями, используйте помеченные регулярные выражения: если конструкция (...) появляется в регулярном выражении, то часть соответствующего ей фрагмента доступна как 1. Возможно до девяти помеченных выражений, на которые ссылаются с помощью 1, 2 и т.д.

s/(...)(.*)/21/ Поместить 3 первых символа в конец
/(..*)1/ Найти строки, содержащие повторяющиеся смежные цепочки символов

Команды, работающие с файлами

Командам r и w (читать и писать) могут предшествовать номера строк:

nr file Читать file; добавить его после строки n; текущей становится последняя прочитанная строка
m,nw file Писать строки m-n в file; положение текущей строки не изменяется
m,nw file Добавить строки m-n к file; положение текущей строки не изменяется

По умолчанию диапазон для w и W (команда W приведена ниже в табл. П.1.2) — это целый файл. Значение n по умолчанию для r равно $, что представляется не очень удачным. Будьте внимательны.

Редактор ed запоминает первое использованное имя файла из командной строки или из команд r, w. Команда f (файл) печатает или заменяет имя запомненного файла:

f Печатать имя запомненного файла
f file Установить запомненное имя на 'file'

Команда e (редактировать) вновь вызывает ed с запомненным или новым файлом:

e Начать редактировать запомненный файл
e file Начать редактировать 'file'

Команда е защищена тем же способом, что и q: если вы не записали измененную версию, первая команда е выдает сообщение об ошибке; е вновь инициализирует редактор независимо от внесения изменений. В некоторых системах ed связан с е, так что одна и та же команда (е filename) может использоваться внутри и вне редактора.

Шифрование

Файлы могут быть зашифрованы по записи и дешифрованы при чтении с помощью команды x; пароль будет запрошен. Шифрование происходит тем же способом, что и в crypt(1). В некоторых системах команда x заменена на X (прописную букву) во избежание случайностей.

Сводка команд

В табл. П.1.2 перечислены команды редактора, а в табл. П.1.3 допустимые номера строк. Каждой команде предшествует нуль, один или два номера строк, указывающие число используемых строк, если их нет, принимается соглашение по умолчанию. За большинством команд может следовать буква p для вывода последней обработанной строки или 1 для формата списка. Текущей обычно становится последняя обработанная строка; настройка не меняется командами f, k, w, x, =, !.

Выполнять ввод до тех пор, пока не напечатана строка, содержащая только '.'
.,.с Заменить строки, новый текст заканчивается так же, как для команды а
.,.d Исключить строки
е file Вновь начать редактировать file. Редактирование начинается даже в том случае, если исправления не записаны
f file Запомнить имя файла как file
1,$g/re/cmds Выполнить cmds для каждой строки, соответствующей регулярному выражению re; отдельные команды в cmds разделены newline (+"перевод строки")
.i Вставить текст перед строкой; он заканчивается так же, как для команды a
.,.+1j .Соединить строки в одну
.kc Пометить строку буквой с
...l Перечислить строки, делая невидимые символы видимыми
.,.m line Переместить строки после строки line
.,.p Печатать строки
q Выйти. Q выходит, даже если исправления не записаны
$r file Читать file
.,.s/re/new/ Заменить new на то, что соответствует re
.,.t line Скопировать строки после line
.u Аннулировать последнюю подстановку в строке (только одну)
1,$v/re/cmds Выполнить команды ed cmds для каждой строки, не соответствующей re
1,$w file Записать строки в файл; W добавляет (строки к файлу) вместо того чтобы записывать (как новый файл)
X Войти в режим шифрования (или ed -х имя_файла)
$= Печатать номер строки
! cmdline Выполнить команду UNIX cmdline
(.+1) newline Печатать строку

Таблица П.1.2: Сводка команд ed

n Абсолютный номер строки n, n = 0,1, 2,...
. Текущая строка
$ Последняя строка текста
/re/ Следующая строка, соответствующая re; после последней $ циклическое движение к первой строке
?re? Предыдущая строка, соответствующая re; после первой циклическое движение к последней $
'c Строка с меткой с
N1+/-n Строка N1+/-n (аддитивная комбинация)
N1,N2 Строки с N1 по N2
N1;N2 Команда: сделать строку N1 текущей, затем вычислить N2. N1 и N2 могут быть определены любым из перечисленных выше способов

Таблица П.1.3: Номера строк в ed

Упражнение

Если вы думаете, что знаете ed, попробуйте выполнить текст (см. справочное руководство по quiz(6)).

Оглавление книги


Генерация: 1.300. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз