linux streams

sed

Потоковый редактор текста — преобразование строк по шаблонам

Описание

sed (stream editor) — потоковый редактор текста, созданный в 1973–1974 годах в Bell Labs Ли Макмэоном. В отличие от интерактивных редакторов, sed читает текст построчно, применяет к каждой строке набор команд и выводит результат. Это делает его идеальным для трансформации потоков данных в пайпах и автоматического редактирования файлов без открытия в редакторе.

Основная команда sed — замена: s/шаблон/замена/флаги. Шаблон — это регулярное выражение. Помимо замены, sed умеет удалять строки (d), вставлять новые строки (a, i), выводить только совпадающие строки (p), работать с диапазонами строк. sed поддерживает адресацию: команды можно применять только к строкам в определённом диапазоне или совпадающим с regex.

В Linux наиболее распространён GNU sed, расширяющий возможности POSIX-совместимого sed: поддержка \w, \s, \+, нечувствительность к регистру (I), редактирование на месте (-i) с поддержкой бэкапа, режим многострочной обработки.

Синтаксис

sed [OPTIONS] 'SCRIPT' [FILE...] sed [OPTIONS] -e SCRIPT [-e SCRIPT] ... [FILE...] sed [OPTIONS] -f SCRIPT_FILE [FILE...]
# Замена первого вхождения в каждой строке sed 's/old/new/' file.txt # Замена всех вхождений (флаг g) sed 's/old/new/g' file.txt # Удалить строки с шаблоном sed '/pattern/d' file.txt # Редактирование файла на месте sed -i 's/old/new/g' file.txt

Флаги и команды

Флаг / Команда Описание Пример
-n Подавить автоматический вывод строк (только явные p) sed -n '/pattern/p' file
-e SCRIPT Добавить команду скрипта (для нескольких команд) sed -e 's/a/A/' -e 's/b/B/' file
-i[SUFFIX] Редактировать файл на месте (inplace); опциональный суффикс для бэкапа sed -i.bak 's/old/new/g' file
-f FILE Читать скрипт из файла sed -f rules.sed data.txt
-E / -r Расширенные регулярные выражения (ERE) — не нужно экранировать +, ?, () sed -E 's/[0-9]+/NUM/g' file
s/RE/repl/g Команда замены; флаг g — все вхождения в строке sed 's/foo/bar/g' file
s/RE/repl/I Флаг I — нечувствительно к регистру (GNU sed) sed 's/error/ERR/gI' log
d Удалить текущую строку sed '/^#/d' config.ini
p Вывести текущую строку (обычно с -n) sed -n '5,10p' file
a TEXT Добавить строку TEXT после текущей (append) sed '/match/a\new line' file
i TEXT Вставить строку TEXT перед текущей (insert) sed '1i\# Header' file
q Выйти после обработки текущей строки sed '5q' file
= Вывести номер текущей строки sed -n '/error/=' log
& В строке замены — ссылка на совпавший текст sed 's/[0-9]*/[&]/' file

Паттерны использования

Замена строк в файле на месте

# Замена с бэкапом
sed -i.bak 's/localhost/production.server.com/g' config.py

# Без бэкапа (GNU sed)
sed -i 's/version = "1.0"/version = "2.0"/' setup.py

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

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

# Удалить комментарии
sed '/^#/d' config.ini
sed '/^[[:space:]]*#/d' config.ini   # с пробелами

# Удалить строки с шаблоном
sed '/DEBUG/d' app.log

Извлечение диапазона строк

# Строки 10–20
sed -n '10,20p' file.txt

# С первой совпадающей до второй
sed -n '/START/,/END/p' file.txt

# Первые 5 строк
sed '5q' file.txt    # аналог head -5

Группы захвата в замене

# Поменять местами два слова
sed -E 's/(\w+) (\w+)/\2 \1/' file

# Обернуть числа в скобки
sed -E 's/([0-9]+)/(\1)/g' file.txt

# Дата из YYYYMMDD в YYYY-MM-DD
sed -E 's/([0-9]{4})([0-9]{2})([0-9]{2})/\1-\2-\3/'

Работа с конфигурационными файлами

# Закомментировать строку
sed -i 's/^OPTION=/#OPTION=/' /etc/app.conf

# Раскомментировать строку
sed -i 's/^#OPTION=/OPTION=/' /etc/app.conf

# Изменить значение параметра
sed -i 's/^timeout=.*/timeout=30/' config.ini

Несколько команд

# Несколько -e
sed -e 's/foo/bar/g' -e 's/baz/qux/g' file

# Через точку с запятой
sed 's/a/A/g; s/b/B/g' file

# Из файла скрипта
cat > rules.sed << 'EOF'
s/old/new/g
/^#/d
EOF
sed -f rules.sed data.txt

Советы и предупреждения

Совет: Если в шаблоне или замене есть слэш /, используйте другой разделитель. Например, для работы с путями: sed 's|/home/user|/home/admin|g' file — удобнее, чем экранировать каждый слэш.
Совет: Символ & в строке замены означает «весь совпавший текст»: sed 's/[0-9]*/(&)/g' — обернёт все числа в скобки без явных групп захвата.
Совет: Используйте -E для расширенных regex, чтобы не экранировать +, ?, (), |: sed -E 's/(error|warning)/[\1]/gi'
Внимание: Флаг -i ведёт себя по-разному в GNU sed (Linux) и BSD sed (macOS). На macOS sed -i '' требует пустой строки как аргумента; в Linux sed -i достаточно. Для переносимости: sed -i.bak работает везде.
Внимание: sed обрабатывает BRE (базовые regex) по умолчанию. В BRE +, ?, (), | требуют экранирования backslash. Используйте -E для более привычного синтаксиса (ERE).