open atlas
↑ К треку
Командная строка CLI · 06 · 03

замены в sed

sed обрабатывает текст построчно. s/old/new/g заменяет regex строкой замены. Адреса (номера строк, /regex/) ограничивают, какие строки редактируются. -i перезаписывает файлы на месте — на macOS требует sed -i '.

CLI Middle ◷ 22 min
Уровень
ОсновыJuniorMiddleSenior

У тебя есть конфигурационный файл с именем хоста, которое нужно изменить. Или экспорт логов, где каждая временна́я метка в неверном формате. Или скрипт, ссылающийся на старый эндпоинт API в пятидесяти местах. Открыть редактор — вариант для одного файла; sed работает с тысячей файлов в конвейере. sed — потоковый редактор (Stream EDitor) — читает текст построчно, применяет набор команд редактирования и выводит результат. Его самая используемая команда — s/old/new/g: найти регулярное выражение, заменить его строкой, повторить для каждого вхождения в строке. Всё остальное в sed — управление тем, к каким строкам применяется замена.

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

Цель

После этого урока ты сможешь использовать sed 's/old/new/g' для глобальной замены, использовать адреса для ограничения редактируемых строк, удалять строки командой d и использовать sed -i (с учётом переносимости на BSD) для перезаписи файлов на месте.

1

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.

2

Адреса ограничивают, к каким строкам применяется команда. Без адреса команда применяется к каждой строке.

  • 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

Адрес + команда — мощная комбинация: позволяет делать хирургические правки, не затрагивая похожие строки в неправильной секции.

3

Команда d удаляет строки. В сочетании с адресом убирает конкретные строки из вывода.

# Удалить все строки комментариев (начинающиеся с #)
sed '/^#/d' nginx.conf

# Удалить пустые строки
sed '/^[[:space:]]*$/d' file.txt

# Удалить строки 1–5 (например, заголовок CSV + метаданные)
sed '1,5d' report.csv

# Удалить последнюю строку
sed '$d' file.txt

d ничего не выводит для совпавшей строки и немедленно переходит к следующей — никакие дальнейшие команды на удалённой строке не выполняются.

Отрицание с !: addr!cmd применяет cmd к строкам, которые НЕ соответствуют адресу.

# Оставить только строки, содержащие 'ERROR' (удалить всё остальное)
sed '/ERROR/!d' app.log

Это эквивалент grep 'ERROR', но демонстрирует систему адресов sed.

4

-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) резервная копия не создаётся.

5

Группы захвата \(...\) и обратные ссылки \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-уровень. Открой, попробуй, потом открой ответ.

вспомнитьприменитьуглубить0 из 4 завершено

Что-то непонятно?

Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.

хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.