Потоковый редактор SED
Sed - лёгкий(бинарник весит всего 128 килобайт) и удобный инструмент обработки текста.
В этой статье я приведу несколько простых примеров использования sed и расскажу о его основных возможностях.
Sed получает входной поток данных или файл построчно, редактирует каждую строку согласно правилам, определённым в sed-скрипте, и затем выводит результат. Sed это тьюринг-полный язык.
Формат команды sed
Команда sed имеет формат:
- sed [ -n ] [ -e скрипт ] [ -f скрипт-файл ] [ файлы ]
Флаг -n подавляет вывод
-e - указывает на список инструкций, заданный в командной строке.
-f - указывает местонахождение файла-скрипта.
Формат команд редактирования
Скриптовый файл состоит из набора команд
- [ адрес [ , адрес ] ] команда [ аргументы ]
по одной в каждой строке.
Адреса это либо номера строк, либо специальные символы, либо регулярное выражение:
$ - последняя строка
начало~N - Каждая N-я строка, начиная с номера начало
/регулярное_выражение/ - строки, попадающие под регулярное_выражение
Примеры:
- 1~2 - Каждая вторая строка
- /REGEXP/ - все строки, в которых встречается /REGEXP/
- 10,20 - строки с 10-й по 20-ю
- 10,+10 - строки с 10-й по 20-ю
- 5,~N - строки начиная с 5-й и до первой, кратной N
- 5,/REGEXP/ - строки, содержащие /REGEXP/, после 5-й(не включая 5-ю)
- Если адрес не указан, обрабатываются все строки.
- Если указан один адрес - обрабатывается соответствующая строка
- Если указаны два адреса, то выбираются строки в заданном интервале.
- !команда - выполняется команда, для строк, которые небыли выбраны по адресам.
Основные команды
Рассмотрим основные команды:
[адрес] a текст - добавить новую строку с текстом после указанной строки
$ cat sed_test
sed_test_1 11111
sed_test_2 22222
sed_test_3 33333
$ sed -e '2 a new_line' sed_test
sed_test_1 11111
sed_test_2 22222
new_line
sed_test_3 33333
[адрес [, адрес]] c текст - Удаляет выбранные строки и заменяет их на текст
$ sed -e '2 с new_line' sed_test
sed_test_1 11111
new_line
sed_test_3 33333
$ sed -e '/3/ с new_line' sed_test
sed_test_1 11111
sed_test_2 22222
new_line
[адрес [, адрес]] d - Удаляет указанные строки
$ sed -e '2 d' sed_test
sed_test_1 11111
sed_test_3 33333
$ sed -e '2!d' sed_test
sed_test_2 22222
[адрес] i текст - Вставить текст на место указанной строки
$ sed -e '2 i new_line' sed_test
sed_test_1 11111
new_text
sed_test_2 22222
sed_test_3 33333
[адрес [, адрес]] p (с флагом -n) выводит найденные строки
$ sed -ne '2p' sed_test
sed_test_2 22222
[адрес] q - выход из sed
[адрес [, адрес]] r файл - Читает файл и выдает его содержание на выход.
[адрес [, адрес]] s/регулярное_выражение/замена/флаги - Заменяет регулярное_выражение на замена-у с учётом флагов:
- g - во всей строке
- i - без учёта регистра
- p - выводить результат замены
$ sed -ne 's/t/T/g' sed_test
sed_TesT_1 11111
sed_TesT_2 22222
sed_TesT_3 33333
$ sed -e 's/[0-9]/d/g' sed_test
sed_test_d ddddd
sed_test_d ddddd
sed_test_d ddddd
[адрес [, адрес]] y/строка1/строка2/ - Заменяет все вхождения символов в строке1 соответсвующими символами из строки2. Длины строк должны быть одинаковыми.
$ sed -ne 'y/est/EST/g' sed_test
SEd_TEST_1 11111
SEd_TEST_2 22222
SEd_TEST_3 33333
[адрес [, адрес]] { команды } - скобки группируют команды
[адрес] = - Выдаёт номера строк
Метки
: метка - сопоставить группе команд метку
b метка - переход к команде, обозначенной меткой метка, если метка отсутствует, то переход в конец командного файла.
t метка - переход к команде, обозначенной меткой метка только после удачной замены с помощью команды s///
Цикл выполнения
sed работает с двумя буферами данных: основным и вспомогательным. Изначально оба буфера пусты.
Работа с этими буферами осуществляется при помощи команд:\`h', `H', `x', `g', `G' `D' h - Заменить содержимое вспомогательного буфера содержимым основного
H - Добавить новую строку к вспомогательному буферу и затем добавить содержимое основного буфера к содержимому вспомогательного
x - Поменять содержимое обоих буферов местами
g - Заменить содержимое основного буфера содержимым вспомогательного
G - Добавить новую строку к основному буферу и затем добавить содержимое вспомогательного буфера к содержимому основного
D - Удалить текст основного буфера до следующего символа перевода строки
N - Добавить новую строку к основному буферу, затем добавить туда следующую обрабатываемую строку
P - Вывести содержимое основного буфера до следующего символа перевода строки
Более сложные примеры
Следующий скрипт меняет местами строки файла (первые строки становятся последними и наоборот)
$ cat tac.sed
#!/usr/bin/sed -nf
# начиная со второй строки, содержимое буфера (который уже содержит
# все предыдущие строки) добавляется к текущей строке.
1! G
# при достижении последней строки - печатаем
$ p
# Заносим данные в буфер опять
h
sed -nf tac.sed sed_test
sed_test_3 33333
sed_test_2 22222
sed_test_1 11111
Считаем строки файла (выводим номер последней строки)
$ cat count.sed
#!/usr/bin/sed -nf
$=
результат
$ sed -nf count.sed sed_test
3
Обращение строк
$ cat revers.sed
#!/usr/bin/sed -f
# пропускаем строки из одной буквы
/../! b
# Переворачиваем строку. Добавляем по пустой строке перед и после текущей.
s/^.*$/\
&\
/
# Переносим первый символ в конец
# цикл работает пока в средней строке есть символы.
tx
:x
s/\(\n.\)\(.*\)\(.\n\)/\3\2\1/
tx
#удаляем лишние переносы строк
s/\n//g
Этот скрипт перемещает две буквы за раз.
$ sed -f revers.sed sed_test
11111 1_tset_des
22222 2_tset_des
33333 3_tset_des
Дополнительная информация
Подробнее о формате sed-скриптов можно узнать, прочитав мануал man sed или техническую документацию info sed.