Статьи

Уроки Unix: sed

sed — это двоичный файл для программы Stream EDitor, присутствующий почти во всех дистрибутивах Unix-подобных систем. Его назначение — выполнять команды выделения, редактирования и удаления над потоком текста; учитывая потоковую природу практически всего в Unix, sed может манипулировать файлами и выводом других команд, что делает его одним из воплощений философии Unix

Это философия Unix: пишите программы, которые делают одно и делают это хорошо. Напишите программы для совместной работы. Написание программ для обработки текстовых потоков , потому что это универсальный интерфейс.

sed может передавать результаты любой команды, чтобы отфильтровать ее, или, говоря функционально, отобразить команду на нее.

команды

По умолчанию команды применяются линейно. Например, команда a добавляет строку текста после каждой совпавшей строки.

$ ls -1 /bin/ | sed -e 'aAFTER' | tail -n 4
zmore
AFTER
znew
AFTER

Команда d удаляет строку, соответствующую определенному шаблону; в этом случае строки, начинающиеся с z.

$ ls -1 /bin/ | sed -e '/^z/d' | tail -n 4
vdir
vmmouse_detect
which
ypdomainname

Более гибкая линейная замена — это знаменитый s :

$ ls -1 /bin/ | sed -e 's/^z//' | tail -n 4
grep
less
more
new

который, как вы можете видеть, соответствует регулярным выражениям, а не только фиксированным строкам.

фильтрация

Также по умолчанию sed выполняет перепечатку на стандартном выводе каждой строки, которая не соответствует командам. Этот режим полезен, когда вам просто нужно отредактировать некоторые строки и оставить без изменений остальные; однако, тихий режим — лучший выбор для выполнения выбора:

$ ls -1 /bin/ | sed -n -e 'p' | tail -n 4
zgrep
zless
zmore
znew

На этот раз мы сказали sed работать в тихом режиме с -n. Однако команда, передаваемая ей через -e, была p , что означает просто печатать каждую строку. Если бы мы убрали переключатель режима без вывода сообщений, этот вывод был бы напечатан:

$ ls -1 /bin/ | sed -e 'p' | tail -n 4
zmore
zmore
znew
znew

который кажется излишним. sed печатает каждую строку ввода и перепечатывает ее после этого с помощью команды p.

Теперь, когда мы можем ничего не печатать по умолчанию, мы можем добавить селекторы в p, чтобы ограничить то, что мы рассматриваем во вводе. Например, мы можем выбрать только строки, соответствующие выражению в стиле grep:

$ ls -1 /bin/ | sed -n -e '/sh$/p'
bash
dash
rbash
sh
static-sh

Или мы можем напечатать с 5 по 8 строку:

$ ls -1 /bin/ | sed -n -e '5,8p'
bzcmp
bzdiff
bzegrep
bzexe

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

$ cat /var/log/onebip/onebip/log-*mailman-sms-connectivity* | sed -n -e '/REQUEST BODY/,/RESPONSE CODE/p' | tail -n 4
2013-10-11T15:21:01  127.0.0.1 REQUEST BODY  {"country":"ES","description":"Super powers","container":"purchase\/999235"}
2013-10-11T15:21:01  127.0.0.1 RESPONSE CODE HTTP/1.1 201 Created
2013-10-11T15:21:03  127.0.0.1 REQUEST BODY  {"country":"IT","description":"Super powers","container":"purchase\/1188829327"}
2013-10-11T15:21:03  127.0.0.1 RESPONSE CODE HTTP/1.1 201 Created

так как выбор может быть выполнен несколько раз, сопоставляя каждую пару REQUEST BODY и RESPONSE CODE в файле (имейте в виду, что это может не масштабироваться до более высоких пропускных способностей, если журналы могут перекрывать друг друга.)

Собираем все вместе:

$ cat /var/log/onebip/onebip/log-*mailman-sms-connectivity* | sed -n -e '/REQUEST BODY/,/RESPONSE CODE/p' | sed -e 's/.*127.0.0.1//g' | tail -n 2
 REQUEST BODY  {"country":"IT","description":"Super powers","container":"purchase\/1188829327","price":100,"smsc":"Mpayit"}
 RESPONSE CODE  HTTP/1.1 201 Created

Выводы

sed находится в базовом наборе инструментов для Unix; с его помощью вы можете редактировать поток теста, подставляя выражения и фильтруя от одной до нескольких строк. Он может использоваться совместно с grep, где последний выполняет тяжелую работу по выбору, а sed редактирует по линиям.

Кроме того, его интерфейс совместим с командами Vim (команды s, p, d), и его не должно быть трудно изучить с небольшой практикой. Когда я читаю учебные пособия такого рода, я нахожу полезным вводить каждую команду, которую я хочу выучить, в моем собственном терминале, поскольку практика приводит к лучшему удержанию, чем чтение.