Редакторы Ed и Sed

Редактор ed - очень простой интерактивный текстовый редактор, включенный в спецификацию стандарта POSIX. Этот редактор должен присутствовать в любой Unix подобной ОС, в том числе Linux. Фактически это так и есть, но некоторые реализациях могут отклоняться от стандарта. Например, busybox в эмуляторе Unix'а MobaXterm выдает приглашение на ввод команд и лишён поддержки регулярных выражений.

Набор команд ed используется в потоковом редакторе sed, а так же в популярном редакторе vim (там они доступны после ввода управляющего символа ':' ).

Редактор ed не имеет пользовательского интерфейса и не выводит на экран текст редактируемого файла. Это позволяет работать с редактором ed на очень медленных линиях связи и при плохом отклике системы (например при чрезмерной нагрузке).

При старте редактор ed считывает редактируемый файл в буфер в оперативной памяти и выполняет все операции с этим буфером. Буфер сохраняется в файл только после явного вызова команды записи. Такой способ редактирования отличает редактор ed от потокового редактора sed и не позволяет работать в ed с большими файлами.

Запуск редактора

ed [file]

Если указано имя файла, то при старте выдаётся число прочитанных байт. В классической реализации приглашение на ввод не выдается, а вывод числа байтов можно подавить опцией '-'. В MobaXterm выдается приглашение ':', а любые опции игнорируются.

Команды sed

Запуск

sed -i.bak -n -e 'cmd' -f cmdfile file1 file2...

По умолчанию, результат обработки выдаётся на стандартный вывод.

  • -i[ext] - редактирование файлов "на месте". Каждый файл обрабатывается отдельно. Результат сохраняется в тот же файл. Старое содержимое сохраняется в файле, к имени которого приписана строка ext.
  • -n - отмена автопечати обработанных строк. Для вывода строк необходимо явно указывать в скрипте команду p или аналогичную.
  • -e cmd - задание скрипта cmd в командной строке
  • -s cmdfile - чтение скрипта из файла cmdfile
  • file1 file2... - список входных файлов. При его отсутствии обрабатывается стандартный ввод.

Формат команд

[addr1 [,addr2]] C [options]

Адреса определяют строки, к которым должна быть применена команда. Если адрес не указан, то команда применяется ко всем строкам. Если указаны два адреса, то команда применяется ко всем строкам от addr1 до addr2 включительно. Адреса могут быть номерами строк (в том числе символ $ в качестве номера последней строки), регулярными выражениями в формате /re/ или \%re% (в этом случае % может быть заменён на любой символ). Запись addr! означает, что команду надо применять ко всем адресам, кроме указанного.

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

В файле отдельные команды могут располагаться в отдельных строках. При запуске однострочных программ команды отделяются точкой с запятой или передаются в виде последовательности опций -e 'cmd'

sed '1d;3d;s/abc/cde/'
sed -e '1d' -e '3,5d' -e '/start/{n;n;s/abc/cde/}'

Основной цикл

Редактор sed оперирует тремя объектами: входной поток строк, буфер строк (pattern space), буфер хранения (hold space), выходной поток. ( pattern space также переводят как "пространство регулярных выражений")

В цикле производятся следующие действия:

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

Команды управления главным циклом

q # если не отключена автопечать, то вытолкнуть буфер строк в выходной поток,
  # завершить главный цикл
n # если не отключена автопечать, то вытолкнуть буфер строк в выходной поток,
  # загрузить из входного потока в буфер строк следующую строку,
  # продолжить выполнять команды уже с новым содержимым

Команды изменения строк

s/from\(.*\)/to\1/gi # замена регулярного выражения в буфере строк
y/abc/cde/ # Замена парных символов в буфере строк. Аналог команды tr.

Вставка/замена/удаление строк

text - последовательность строк, разделяемых комбинацией символов \<перевод строки>.

i  text # вывести в выходной поток указанный текст
a  text # вытолкнуть буфер строк в выходной поток,
        # затем вывести в выходной поток указанный текст
c  text # замена строк. Удалить строки в диапазоне из входного потока,
        # затем вывести в выходной поток указанный текст
d # очистить буфер строк и перейти на начало главного цикла
D # удалить первую строку в буфер строк
  # и перейти на начало главного цикла без считывания новой строки

Команды управления буферами

N # добавить в буфер строк перевод строки и следующую строку из входного потока
g # скопировать буфер хранения в буфер строк
G # добавить в буфер строк перевод строки и содержимое буфера хранения
h # скопировать буфер строк в буфер хранения 
H # добавить в буфер хранения перевод строки и содержимое буфера строк
x # поменять местами буфер строк и буфер хранения 

Если буфер хранения пуст, то команда G добавляет в буфер строк только перевод строки.

Печать

Опция -n отключает автоматический вывод результата в выходной поток. В этом случае команды печати надо указывать явно.

p # скопировать (не очищая) буфер строк в выходной поток
P # скопировать первую строку буфера строк в выходной поток
l # скопировать  буфер строк в выходной поток,
  # предварительно пометив конец строки знаком $,
  # и заменив непечатаемые символы их кодами в стиле языка Си
= # вывести номер текущей строки + перевод строки в выходной поток

Команды работы с файлами

r filename # вывести содержимое файла в выходной поток перед началом следующего цикла.
w filename # записать буфер строк в конец файла. При запуске скрипта файл обнуляется.

Метки и ветвления

: LABEL # метка
b [LABEL] # безусловный переход на метку, а при ее отсутствии на начало главного цикла
t [LABEL] # переход на метку в случае успешного выполнения хотя бы одной команды 's'.
        # При отсутствии метки переход на начало главного цикла

Команды редактора ed

Структура команд

Большинство команд ed имеют вид:

[addr]C[args]

Где addr - адреса строк, к которым надо применить команду, C - односимвольная команда, args - дополнительные аргументы команды. Адрес addr может отсутствовать, указывать на одну строку или на диапазон строк. По умолчанию, команды редактирования применяется к текущей строке, а файловые команды ко всему буферу.

Адреса

Адреса задаются следующими способами:

По номерам (n обозначает число), как результат поиска регулярного выражения, как смещение относительно известного адреса или как диапазон от адреса до адреса:

  • n - номер строки. 0 означает строку перед первой;
  • $ - последняя строка в буфере;
  • . - текущая строка. На старте устанавливается в $;
  • /RE/ - первая строка соответствующая регулярному выражению RE. Поиск идёт вниз по тексту Если RE не найдено до конца, то поиск продолжается по кругу с начала. В sed - все строки соответствующие выражению RE.
  • ?RE? - то же, что и /RE/. но поиск идёт вверх по тексту . Не актуально для sed.
  • addr+n или addr-n - смещение относительно адреса, например, /RE/+2 или $-3 (четвертая строка с конца);
  • addr1,addr2 - диапазон от и до включительно;
  • [addr1,addr2]g/RE/ - все строки в диапазоне addr1-addr2, соответствующие регулярному выражению RE;
  • [addr1,addr2]v/RE/ - все строки в диапазоне addr1-addr2, не соответствующие регулярному выражению RE;
  • 'C - строка, помеченная символом C. Метка устанавливается командой [addr]kC.

Диапазон может указываться через точку с запятой. В этом случае если адрес addr2 задан в виде поиска регулярного выражения, то при использовании запятой поиск ведётся от строки, следующей за текущей строкой, а при использовании точки с запятой - от строки, следующей за адресом addr1.

Команды

Общие

  • q - завершить работу
  • Q - забыть изменения и завершить работу
  • u - отменить изменения, сделанные последней командой редактирования
  • f file - задать текущее имя файла. Удобно если ed запускался без указания имени файла.
  • [addr]r file - вставить содержимое файла после адреса. По умолчанию в конец буфера. r !cmd - выполнить шелловскую команду и вставить её вывод
  • e file - удалить содержимое буфера и начать редактировать новый файл. e !cmd - аналогично r !cmd
  • [addr1,addr2]w[ file] - записать буфер в файл (можно указать новое имя)

Ввод строк

  • [addr]a - вставить строки после указанной
  • [addr]i - вставить строки перед указанной
  • [addr1,addr2]с - удалить строки из диапазона и вставить вместо них новые

В командах вставки признаком конца ввода является строка состоящая из одного символа точки и перевода строки. Для ввода одной точки в строке вводятся две точки.

Печать строк

  • [addr1,addr2]p - напечатать строки из диапазона
  • [addr1,addr2]n - напечатать строки из диапазона, вставив перед каждой её номер и символ табуляции.

Удаление и копирование

  • [addr1,addr2]d - удалить строки
  • [addr1,addr2]m[addr] - переместить строки в позицию после адреса addr. Если addr==0, то в начало буфера.
  • [addr1,addr2]m[addr] - скопировать строки в позицию после адреса addr.

Контекстная замена

  • s/SRC/DST/opt произвести контекстную замену в строке. Opt: g - все вхождения в строке, i - игнорировать регистр.

Регулярные выражения

  • Для группировки используются скобки \( и \)
  • Найденные группы обозначаются \1, \2...
  • ^, ., $ - начало строки, произвольный символ, конец строки
  • * - повторитель предыдущего символа или группы от 0 до бесконечности
  • {m,n} - повторитель от m до n. {m} означает ровно m вхождений; {m,} - по крайней мере m вхождений; {m,n} - любое число вхождений от m до n включительно