Learning Platform
Глоссарий Troubleshooting
Урок 09.02 · 22 мин
Средний
sedAddressesdeleteprintRangePatterns

Что такое addresses в sed

Каждая команда sed может быть ограничена адресами: к каким строкам её применять. Формат:

[ADDR][,ADDR2] COMMAND
  • Без адресов — команда применяется ко всем строкам
  • Один адрес — только к строкам, соответствующим адресу
  • Два адреса через запятую — диапазон с первой по вторую
$ sed '3d' file              # удалить строку 3
$ sed '1,5d' file            # удалить строки 1-5
$ sed '/pattern/d' file      # удалить строки, совпадающие с pattern
$ sed '10,$d' file           # удалить строки с 10-й до конца ($ = last line)
$ sed '/^#/d' file           # удалить все комментарии
$ sed '$!d' file             # удалить все КРОМЕ последней (! инвертирует address)

Виды адресов

Типы sed-адресов

От line number до regex.

N (число)конкретная строкаsed '5d' — только строка 5. Нумерация с 1, не с 0.
$последняя строкаsed '$d' — удалить последнюю строку. Удобно для прокладок (если файл заканчивается на extra newline).
N,Mдиапазон строкsed '5,10d' — удалить строки 5-10. Включительно с обоих концов.
N,$с N до концаsed '10,$d' — удалить с 10-й строки до конца файла.
/regex/строки, совпадающие с regexsed '/ERROR/d' — удалить все строки с 'ERROR'. Pattern обернут в /.../. Альтернативный delimiter тоже работает через \\@regex@d.
/start/,/end/диапазон по regexsed '/BEGIN/,/END/d' — удалить от первой строки 'BEGIN' до первой строки 'END' (включительно). Полезно для удаления секций конфига.
N~stepкаждая N-я строка (GNU)sed '0~2d' — каждую вторую (чётную) строку удалить. GNU-расширение, на BSD не работает.
!инвертирование адресаsed '/regex/!d' — удалить все строки, НЕ соответствующие regex (т.е. оставить только совпадающие). ! инвертирует любой адрес.

Команда d: delete

Удаляет строку из output. Самая частая команда с адресами.

# Удалить первую строку (header CSV)
$ sed '1d' data.csv

# Удалить строки 1-5
$ sed '1,5d' file

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

# Удалить все комментарии (# в начале)
$ sed '/^#/d' /etc/ssh/sshd_config

# Удалить comments и empty lines одной командой
$ sed -e '/^#/d' -e '/^$/d' /etc/ssh/sshd_config
# или альтернативный синтаксис:
$ sed '/^#\|^$/d' /etc/ssh/sshd_config    # BRE с \|
$ sed -E '/^(#|$)/d' /etc/ssh/sshd_config # ERE

d — это «не выводи эту строку и переходи к следующей». Внутри sed это команда «пропусти оставшиеся команды для этой строки», но в pipeline эффект — удаление.

Команда p и -n: print only matching

$ sed '/ERROR/p' file
# Странно: выводит ВСЕ строки, и ERROR-строки ДВАЖДЫ

Почему? sed по умолчанию выводит каждую обработанную строку. Команда p явно дублирует output. Чтобы получить только matching:

$ sed -n '/ERROR/p' file
# -n (quiet) выключает default print
# теперь только команды p реально выводят

-n и p всегда работают парой. Это эквивалентно grep ERROR file, но sed может делать substitution в одной команде:

$ sed -n 's/ERROR.*dag_id=\([a-z_]*\).*/\1/p' app.log
# Выводит только dag_id из строк с ERROR — substitution + p в одной команде

p после s/.../.../ означает: «если substitution произошёл — print». Это мощный idiom: matching + transform + output одной командой.

Команда q: quit

$ sed '10q' file
# Вывести первые 10 строк и завершиться
# Эквивалент head -n 10, но быстрее на больших файлах:
# sed читает до 10-й строки и выходит, head может буферизовать больше
# Вывести строки от начала до первой ERROR
$ sed '/ERROR/q' app.log
# (включая саму строку с ERROR)

DE-сценарии

1. Очистка конфига (без комментариев и пустых строк)

$ sed '/^[[:space:]]*#/d; /^[[:space:]]*$/d' /etc/airflow/airflow.cfg

[[:space:]]* — учесть пробелы/табы перед # или в пустой строке. ; разделяет несколько команд внутри одного sed-вызова.

2. Извлечь строки между двумя маркерами

# Извлечь Python-блок между BEGIN_CODE и END_CODE
$ sed -n '/BEGIN_CODE/,/END_CODE/p' notebook.md

/start/,/end/ — диапазон по regex. Полезно для:

  • Извлечения секций конфигов
  • Очистки markdown-кодоблоков
  • Парсинга structured logs (где stack-trace между маркерами)

3. Удалить header без tail -n +2

$ sed '1d' data.csv
# Эквивалент tail -n +2 data.csv, но работает в pipeline без extra процесса

4. Замена в конкретной строке

# Заменить slug в 1-й строке Markdown header
$ sed '1s/Old Title/New Title/' README.md

Адрес + s-команда: substitution применяется только к строкам, попадающим в адрес.

# Закомментировать строки 10-20
$ sed '10,20s/^/# /' file

5. Удалить trailing whitespace во всём файле

$ sed -i 's/[[:space:]]*$//' file.py

6. Преобразовать CRLF -> LF (Windows -> Unix)

$ sed -i 's/\r$//' file
# \r = CR (Windows line ending CRLF = \r\n; на Unix только \n)

Несколько команд в одном вызове

Три способа:

# 1. Через -e
$ sed -e '1d' -e 's/foo/bar/g' -e '/^$/d' file

# 2. Через ; внутри 'программы'
$ sed '1d; s/foo/bar/g; /^$/d' file

# 3. Через \n (новые строки)
$ sed '1d
s/foo/bar/g
/^$/d' file

Все эквивалентны. На производстве -e или ; — наиболее читаемо.

Sed scripts из файла

Большие sed-программы пишут в файл и подключают через -f:

# /tmp/clean.sed
1d
s/[[:space:]]*$//
/^[[:space:]]*#/d
/^[[:space:]]*$/d

$ sed -f /tmp/clean.sed input.txt

Удобно для reusable transformation pipelines.

Sed hold space — для продвинутых

Sed имеет два буфера: pattern space (текущая строка, default) и hold space (вторичный буфер). Команды h, H (copy to hold), g, G (copy from hold) позволяют делать multi-line операции:

# Reverse порядок строк (tac равен этому):
$ sed '1!G;h;$!d' file

Это «sed magic». Для DE редко нужно — лучше переключиться на awk или perl, которые имеют переменные.

Попробуй сам

  1. Удалить первую строку:
    printf "header\na\nb\nc\n" | sed '1d'
    # -> a, b, c
  2. Удалить пустые строки:
    printf "a\n\nb\n\nc\n" | sed '/^$/d'
  3. Извлечь диапазон:
    seq 1 20 | sed -n '5,10p'
    # -> 5, 6, 7, 8, 9, 10
  4. Замена только в первой строке:
    printf "title\ntitle\ntitle\n" | sed '1s/title/MAIN/'
  5. Удалить комментарии и пустые в /etc/ssh/sshd_config:
    sed '/^#/d; /^$/d' /etc/ssh/sshd_config | head

macOS-различия

  • BSD sed на macOS:
    • N,$ (диапазон до конца) — работает
    • /regex/d — работает
    • \b, \d, \s — НЕ поддерживаются, используй POSIX-классы ([[:alnum:]])
    • N~step (каждая N-я) — не поддерживается, GNU-only
    • -i требует empty arg (см. урок 1)
  • Альтернативный delimiter \@regex@d — может потребовать backslash перед делимитером на BSD.
  • Для cross-platform — perl -ne 'next if /^#/; print' (perl на обеих платформах одинаков).
Проверка знанийKnowledge check
Объясни разницу между 'sed /ERROR/p file' и 'sed -n /ERROR/p file'. Почему первая выглядит 'странно'?
ОтветAnswer
sed по default печатает каждую обработанную строку (autoprint). Команда p — это 'print pattern space сейчас'. Без -n: sed читает строку -> команда p применяется к строкам с ERROR -> ОНИ дважды выводятся (раз от p, раз от autoprint в конце цикла). Другие строки выводятся раз (только autoprint). Итог: все строки + ERROR-дубли. Это редко то, что хочешь. С -n: -n выключает autoprint. Теперь выводятся только строки, где была явная команда p. Результат: только ERROR-строки, как grep ERROR. Правило: -n и p ВСЕГДА вместе, когда нужен grep-подобный фильтр через sed. Главное преимущество перед grep: можно делать transformation одной командой: sed -n 's/ERROR.*dag_id=\(\w+\).*/\1/p' — extract + filter + transform в одной строке. Альтернативное общее правило: думай о sed как о 'autoprint включён по умолчанию' — команды d/p/q/n влияют на autoprint поведение.

Главное

  • Адреса: N (line), N,M (range), $ (last), /regex/, /start/,/end/.
  • ! инвертирует адрес: '$!d' = «удалить все кроме последней».
  • d — delete (skip output). p — print explicitly. q — quit after match.
  • -n (quiet) выключает default autoprint; нужен с p для grep-эффекта.
  • Несколько команд: -e CMD -e CMD или 'CMD1; CMD2'.
  • Большие программы — в файл, подключать через sed -f file.sed.
  • Sed hold space — для multi-line магии (используется редко, лучше awk/perl).

Проверьте понимание

Результат: 0 из 0
Концептуальный
Вопрос 1 из 4. Команда 'sed /^#/d /etc/sshd_config' что делает?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 5