sed: что такое, зачем нужен
Что это такое “потоковый редактор”?
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
Что еще почитать
man sed
(чтение фундаментальное, но непростое)- https://www.digitalocean.com/community/tutorials/the-basics-of-using-the-sed-stream-editor-to-manipulate-text-in-linux