Что это такое “потоковый редактор”?

sed – это программа для неинтерактивного изменения (редактирования) текста.

“Потоковый” как раз означает “неинтерактивный”; то есть способный работать в командной строке и из скриптов.

Что делает sed?

sed-у надо передать текстовый файл и команды, которые надо выполнить над текстом.

Файл можно указать на диске, а можно передать через стандартный входной поток (stdin).

Результат (текст с примененными командами) можно получить в stdout, а можно записать в файл на диске.

Как это выглядит?

В качестве исходного текста возьмем начало файла /etc/passwd:

cat /etc/passwd |head -n 3

Результат выглядит как-то так:

daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin

Заменим все буквы o на #:

cat /etc/passwd |head -n 3 |sed -e 's/o/#/g'

Результат:

daem#n:x:1:1:daem#n:/usr/sbin:/usr/sbin/n#l#gin
bin:x:2:2:bin:/bin:/usr/sbin/n#l#gin
sys:x:3:3:sys:/dev:/usr/sbin/n#l#gin

Замена одной подстроки на другую – самая частая операция, для которой пригождается sed в повседневной жизни.

Больше примеров см. ниже в разделе Примеры.

Когда удобно неинтерактивное редактирование?

1. Когда надо типовым образом изменить много файлов

Например, в шаблонах jekyll-сайта заменить переменную site.url на переменную site.real_url:

sed -i 's/site.url/site.real_url/g' feed.xml _includes/head.html

Или в исходниках того же jekyll-сайта в сентябрьских постах поменять базовый шаблон c post на post2:

find _posts/ |grep 2021-09 |xargs sed -i 's/^layout: *post/layout: post2/'

2. Когда надо поменять файл из скрипта

Например, в Makefile для jekyll-сайта можно написать что-нибудь в таком духе:

new-post
	filename=$$( echo source/_posts/`date '+%Y-%m-%d'`-new-post.md ) ; echo $$filename ; cp template.md $$filename ; sed -i 's/^date:.*/date: '"`date '+%Y-%m-%d %H:%M:%S %z'`"'/' $$filename

Здесь sed заменяет строчку с датой из шаблона на текущую дату-время.

Примеры

Подготовим отдельный файл для экспериментов:

head -n 15 /etc/passwd > /tmp/file-for-sed

Замена текста

Заменить первое вхождение bin в строке на bom:

sed -e 's/bin/bom/' /tmp/file-for-sed

Заменить все вохождения bin на bom:

sed -e 's/bin/bom/g' /tmp/file-for-sed

Эскейпинг (экранирование)

Заменим символы слеша / на #:

sed -e 's/\//#/g' /tmp/file-for-sed

Обратите внимание на конструкцию \/. Это экранирование или эскейпинг: обратный слеш делает следующий символ просто символом, не частью команды s///.

Экскейпинг надо понимать и уметь пользоваться. Но для простых случаев есть способ попроще. Команда замены (s) может использовать любой символ после себя. То есть вместо s/.../.../ может быть s!...!...!, или s#...#...#, или sA...A...A, и так далее.

Таким образом, заменить / на # можно например так:

sed -e 's!/!#!g' /tmp/file-for-sed

Удалить одну или несколько строчек

Удалить строчку номер 2:

sed -e '2d' /tmp/file-for-sed

Удалить строчки с 5 по 10 включительно и еще 12-ю:

sed -e '5,10d;12d' /tmp/file-for-sed

Удалить строчки, начинающуюся с sy:

sed -e '/^sy/d' /tmp/file-for-sed

Удалить строчки, содержащие nologin:

sed -e '/nologin/d' /tmp/file-for-sed

Добавить строчку

Добавить строчку из четырех минусов после каждой строчки, которая начинается с sy:

sed '/^sy/a----' /tmp/file-for-sed

Здесь a – это команда добавления текста (append).

Добавить строчку из четырех минусов после 3-й строчки:

sed '3a----' /tmp/file-for-sed

Изменить исходный файл на диске

Параметр -i говорит sed-у не выводить результат на stdout, а поменять исходный файл.
Например, удалить строчку номер 2 в файле:

sed -i -e '2d' /tmp/file-for-sed

Проверить содержимое файла:

cat /tmp/file-for-sed

Что еще почитать