замены в sed
sed обрабатывает текст построчно. s/old/new/g заменяет regex строкой замены. Адреса (номера строк, /regex/) ограничивают, какие строки редактируются. -i перезаписывает файлы на месте — на macOS требует sed -i '.
У тебя есть конфигурационный файл с именем хоста, которое нужно изменить. Или экспорт логов, где каждая временна́я метка в неверном формате. Или скрипт, ссылающийся на старый эндпоинт API в пятидесяти местах. Открыть редактор — вариант для одного файла; sed работает с тысячей файлов в конвейере. sed — потоковый редактор (Stream EDitor) — читает текст построчно, применяет набор команд редактирования и выводит результат. Его самая используемая команда — s/old/new/g: найти регулярное выражение, заменить его строкой, повторить для каждого вхождения в строке. Всё остальное в sed — управление тем, к каким строкам применяется замена.
К концу урока ты сможешь выполнять глобальные замены, ограничивать правки конкретными строками или диапазонами адресов, удалять строки по шаблону и безопасно редактировать файлы на месте.
После этого урока ты сможешь использовать sed 's/old/new/g' для глобальной замены, использовать адреса для ограничения редактируемых строк, удалять строки командой d и использовать sed -i (с учётом переносимости на BSD) для перезаписи файлов на месте.
s/REGEX/ЗАМЕНА/ФЛАГИ — основная команда sed. Символы / — разделители; вместо них можно использовать любой другой символ, что удобно, когда шаблон содержит слэши.
echo "hello world" | sed 's/world/earth/'
# hello earthБез флагов s заменяет только первое совпадение в каждой строке.
Флаг g заменяет все совпадения в строке.
echo "aaa bbb aaa" | sed 's/aaa/zzz/g'
# zzz bbb zzzБез g только первое aaa стало бы zzz.
Альтернативный разделитель: когда шаблон содержит /, используй другой разделитель, чтобы избежать экранирования.
sed 's|/old/path|/new/path|g' config.txtИспользуется | как разделитель. Работает любой неалфавитно-цифровой символ: s#old#new#g, s,old,new,g.
Адреса ограничивают, к каким строкам применяется команда. Без адреса команда применяется к каждой строке.
N— номер строки:3s/old/new/применяется только к строке 3.$— последняя строка:$dудаляет только последнюю строку./REGEX/— строки, соответствующие шаблону:/^#/dудаляет строки комментариев.N,M— диапазон строк:2,5s/foo/bar/редактирует строки 2–5./НАЧАЛО/,/КОНЕЦ/— диапазон между двумя шаблонами:/BEGIN/,/END/s/x/y/редактирует строки от первого совпаденияBEGINдо следующегоEND.
# Заменить только в строках 10–20
sed '10,20s/debug/info/g' app.log
# Заменить только в строках, содержащих 'ERROR'
sed '/ERROR/s/localhost/prod-server/g' config.logАдрес + команда — мощная комбинация: позволяет делать хирургические правки, не затрагивая похожие строки в неправильной секции.
Команда d удаляет строки. В сочетании с адресом убирает конкретные строки из вывода.
# Удалить все строки комментариев (начинающиеся с #)
sed '/^#/d' nginx.conf
# Удалить пустые строки
sed '/^[[:space:]]*$/d' file.txt
# Удалить строки 1–5 (например, заголовок CSV + метаданные)
sed '1,5d' report.csv
# Удалить последнюю строку
sed '$d' file.txtd ничего не выводит для совпавшей строки и немедленно переходит к следующей — никакие дальнейшие команды на удалённой строке не выполняются.
Отрицание с !: addr!cmd применяет cmd к строкам, которые НЕ соответствуют адресу.
# Оставить только строки, содержащие 'ERROR' (удалить всё остальное)
sed '/ERROR/!d' app.logЭто эквивалент grep 'ERROR', но демонстрирует систему адресов sed.
-i редактирует файлы на месте. Вместо вывода в stdout sed -i перезаписывает файл напрямую. Это важно для скриптового управления конфигурацией и массового переименования.
# GNU sed (Linux)
sed -i 's/old_hostname/new_hostname/g' /etc/hosts
# Переименование сразу в нескольких файлах
sed -i 's/deprecated_func/new_func/g' src/*.pyВсегда тестируй без -i сначала — выведи в stdout и визуально проверь замену перед изменением файлов.
-i поддерживает опциональный суффикс резервной копии: sed -i.bak 's/old/new/g' file сохраняет оригинал как file.bak. Без суффикса (GNU sed) или с пустой строкой суффикса (BSD sed) резервная копия не создаётся.
Группы захвата \(...\) и обратные ссылки \1. Стандартный sed использует BRE (базовые регулярные выражения), где синтаксис группы — \(...\), а обратные ссылки — \1, \2.
# Поменять местами первое и второе поля, разделённые двоеточием
echo "alice:admin" | sed 's/\([^:]*\):\([^:]*\)/\2:\1/'
# admin:alice\([^:]*\) захватывает «всё до двоеточия» как группу 1. Второй \([^:]*\) захватывает второе поле как группу 2. Замена \2:\1 меняет их местами.
Для расширенного regex с более чистым синтаксисом (+, ?, |, группы без обратного слэша) используй -E:
echo "2025-06-19" | sed -E 's/([0-9]{4})-([0-9]{2})-([0-9]{2})/\3\/\2\/\1/'
# 19/06/2025Убрать ANSI-коды цветов из лог-файла, чтобы он читался в обычном текстовом просмотрщике.
ANSI escape-последовательности выглядят как \e[31m (красный) или \e[0m (сброс). Шаблон: ESC[ с числами и буквами.
sed 's/\x1b\[[0-9;]*[a-zA-Z]//g' colored.log > clean.log\x1b — шестнадцатеричный escape для символа ESC (0x1B). \[[0-9;]*[a-zA-Z] совпадает с остатком последовательности. Флаг g удаляет все вхождения в строке.
Массовая замена эндпоинта API по всей кодовой базе:
find . -name '*.js' -exec sed -i 's|https://api.old.com|https://api.new.com|g' {} +find находит все .js файлы; -exec sed -i ... {} + запускает sed -i на каждой пачке. Разделитель | избегает экранирования / в URL.
▸Почему это работает
BSD sed (macOS) требует явного указания суффикса резервной копии после -i — даже пустая строка должна быть передана явно. GNU sed (Linux) воспринимает -i без аргумента как «без резервной копии». Это значит, что sed -i 's/old/new/g' file работает на Linux, но не работает на macOS с ошибкой sed: 1: "file": invalid command code f. Переносимая форма: sed -i '' 's/old/new/g' file (macOS) против sed -i 's/old/new/g' file (Linux). Для скриптов, работающих на обеих платформах, определяй платформу или используй perl -i -pe 's/old/new/g' file — он ведёт себя одинаково везде.
▸Частая ошибка
Забыть флаг g — самая распространённая ошибка в sed. sed 's/foo/bar/' заменяет только первое вхождение в каждой строке — если строка содержит foo foo, второй foo остаётся нетронутым. Используй g, если только специально не нужно только первое совпадение. Ещё одна ловушка: sed -i без предварительного прогона вывода в stdout. Всегда тестируй sed 's/шаблон/замена/g' file | head -20 перед добавлением -i — плохой regex с -i и без резервной копии перезапишет файл мусором.
Ты запускаешь: sed '/^#/d' config.txt. Что делает эта команда?
sed 's/REGEX/ЗАМЕНА/g' заменяет все совпадения в каждой строке. Без g меняется только первое совпадение в строке. Адреса (номера строк, /regex/, диапазоны N,M) ограничивают, к каким строкам применяется команда. Команда d удаляет совпавшие строки. -i перезаписывает файлы на месте — всегда делай пробный прогон; на macOS используй sed -i '', на Linux — sed -i. Группы захвата (\(...\) в BRE, (...) с -E) и обратные ссылки (\1, \2) позволяют переставлять поля и переформатировать данные. Используй альтернативный разделитель вроде |, когда шаблон или замена содержат слэши.
Практика
Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.
Что-то непонятно?
Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.