sed и awk в Linux: замена текста и однострочники с примерами
Замена строки через sed делается командой sed -i 's/старое/новое/g' файл: ключ -i пишет результат в сам файл, флаг g меняет все совпадения в строке. awk нужен, когда работа идёт со столбцами: awk '{print $1}' выводит первое поле. Ниже рабочие однострочники, шпаргалка и разбор частых ошибок.

Содержание
Когда брать sed, а когда awk
Обе утилиты читают текст построчно и есть в любом дистрибутиве, но думают о строке по-разному. sed видит строку как текст и хорош в правке: заменить, удалить, вставить. awk видит строку как набор полей (столбцов) и хорош в выборке и подсчётах: вывести третий столбец, сложить размеры, посчитать IP-адреса в логе.
Простое правило: если задача звучит как "поменяй", берите sed; если как "покажи, где" или "посчитай, сколько", берите awk. Для поиска строк без изменения хватит grep, о нём в статье о поиске через find и grep.
Версии на октябрь 2026: GNU sed 4.9 в Debian 13, Ubuntu 26.04 и Fedora 44, в Arch уже 4.10. С awk интереснее. В Fedora и Arch команда awk - это GNU awk (gawk), а в Debian и Ubuntu по умолчанию стоит более лёгкий mawk. Базовые однострочники работают в обоих, но расширения gawk (правка на месте, gensub, разбор CSV) в mawk отсутствуют. Проверить и доустановить:
awk --version 2>/dev/null || awk -W version
# Debian, Ubuntu, Mint
sudo apt install gawk
# Fedora (gawk уже есть), Arch
sudo pacman -S gawksed: замена строки и подстроки
Основная команда sed - s/что/на_что/флаги. Без флагов меняется только первое совпадение в каждой строке, флаг g меняет все.
# вывести результат на экран, файл не меняется
sed 's/http:/https:/' links.txt
# все совпадения в строке
sed 's/http:/https:/g' links.txt
# без учёта регистра (GNU sed)
sed 's/error/ERROR/gI' app.log
# только второе совпадение в строке
sed 's/;/,/2' data.txt
# заменить только в строках 10-20
sed '10,20s/foo/bar/g' file.txt
# заменить только в строках, где есть слово listen
sed '/listen/s/80/8080/' site.confСлеши, спецсимволы и группы
Если в тексте есть /, сменить разделитель проще, чем экранировать каждый слеш: подходит любой символ после s.
sed 's|/usr/local/bin|/opt/bin|g' script.sh
# точка в шаблоне означает любой символ, экранируйте её
sed 's/example\.ru/example.org/g' nginx.conf
# & в замене подставляет найденное целиком
sed 's/[0-9]\+/[&]/g' file.txt
# расширенные регулярки (-E) и группы: 2026-10-23 в 23.10.2026
sed -E 's/([0-9]{4})-([0-9]{2})-([0-9]{2})/\3.\2.\1/g' dates.txtБез -E sed использует базовые регулярные выражения: в них +, ?, (, { надо экранировать обратным слешем. С -E они работают как в большинстве языков. Это самая частая причина, почему замена "не срабатывает".
sed -i: правка файла на месте
Ключ -i записывает результат обратно в файл. Без него sed только печатает изменённый текст, а исходник остаётся прежним.
# сначала проверить, что поменяется
sed 's/old/new/g' config.ini | diff config.ini -
# затем применить
sed -i 's/old/new/g' config.ini
# с резервной копией config.ini.bak
sed -i.bak 's/old/new/g' config.ini
# откат
mv config.ini.bak config.iniПривычка, которая экономит нервы: сначала запустите команду без -i и прогоните вывод через diff. Для системных файлов в /etc всегда добавляйте суффикс копии, sed -i.bak стоит пары лишних символов.
Замена во многих файлах
# найти файлы со старым доменом и заменить в них
grep -rlZ 'old.example.ru' /var/www/site | xargs -0 sed -i 's/old\.example\.ru/new.example.ru/g'
# то же через find, только *.php
find /var/www/site -name '*.php' -exec sed -i 's/old\.example\.ru/new.example.ru/g' {} +Две тонкости GNU sed. Первая: -i не редактирует файл, а создаёт новый и подменяет старый. Если файл был символической ссылкой, ссылка заменится обычным файлом; чтобы править цель, добавьте --follow-symlinks. Вторая: синтаксис -i на macOS (BSD sed) другой, там нужен аргумент -i '', поэтому скрипты, скопированные с Mac, иногда падают в Linux.
Удалить, вставить и вывести строки
# вывести строки 10-20
sed -n '10,20p' file.txt
# вывести блок между маркерами
sed -n '/BEGIN CERT/,/END CERT/p' bundle.pem
# удалить строку 5 и последнюю
sed -i '5d;$d' file.txt
# убрать комментарии и пустые строки (удобно для просмотра конфигов)
sed '/^[[:space:]]*#/d;/^[[:space:]]*$/d' /etc/samba/smb.conf
# вставить строку перед 1-й и после строки с шаблоном
sed -i '1i # managed by ansible' app.conf
sed -i '/^\[mysqld\]/a max_connections = 300' my.cnf
# заменить строку целиком
sed -i '/^server_name/c server_name example.org;' site.conf
# закомментировать строку с параметром
sed -i 's/^Option=yes/#&/' app.conf
# заменить только первое совпадение во всём файле (GNU)
sed -i '0,/localhost/s//127.0.0.1/' hosts.txt
# убрать виндовые переводы строк
sed -i 's/\r$//' script.shЕсли нужно подставить значение из переменной, берите двойные кавычки: в одинарных переменная не раскроется. И помните, что слеш или амперсанд в значении сломает выражение, поэтому для путей выбирайте другой разделитель:
NEWDIR=/srv/backup
sed -i "s|^backup_dir=.*|backup_dir=${NEWDIR}|" app.confНесколько правок за один проход
Команды можно разделять точкой с запятой, передавать отдельными ключами -e или сложить в файл и подключить через -f. Файл со списком правок удобно хранить рядом с проектом и применять одинаково на всех серверах:
sed -i -e 's/^Port=.*/Port=2222/' -e 's/^Debug=.*/Debug=no/' app.conf
# fixes.sed: по одной команде на строку
cat fixes.sed
s/^Port=.*/Port=2222/
s/^Debug=.*/Debug=no/
/^#legacy/d
# применить
sed -i.bak -f fixes.sed app.confФлаг --debug (GNU sed 4.6 и новее) печатает, как sed понял программу и что делает с каждой строкой. Он выручает, когда длинное выражение молча ничего не меняет. Если правок много и они сложные, иногда быстрее открыть файл в редакторе: в vim работает та же команда :%s/старое/новое/g.
Шпаргалка: ключи и команды sed и awk
| Конструкция | Утилита | Что делает |
|---|---|---|
s/a/b/g | sed | Заменить все a на b в строке |
-i, -i.bak | sed | Правка на месте, с копией |
-n + p | sed | Печатать только выбранные строки |
d, a, i, c | sed | Удалить, добавить после, вставить до, заменить строку |
-E | sed | Расширенные регулярные выражения |
-F: | awk | Разделитель полей (здесь двоеточие) |
$1, $NF, $0 | awk | Первое поле, последнее поле, вся строка |
NR, NF | awk | Номер строки, число полей в строке |
BEGIN{}, END{} | awk | Блоки до чтения и после чтения всех строк |
-v x=1 | awk | Передать переменную из оболочки |
sub(), gsub() | awk | Замена первого и всех совпадений |
awk: столбцы, разделители и условия
Программа awk состоит из пар условие { действие }. По умолчанию поля разделяются пробелами и табуляциями, а $1, $2 и так далее - это столбцы текущей строки.
# второй и последний столбец
awk '{print $2, $NF}' file.txt
# пользователи с UID от 1000: имя и домашний каталог
awk -F: '$3 >= 1000 {print $1, $6}' /etc/passwd
# строки длиннее 120 символов
awk 'length($0) > 120' code.py
# строки с 5-й по 10-ю
awk 'NR>=5 && NR<=10' file.txt
# разделы, заполненные больше чем на 80%
df -h | awk 'NR>1 && $5+0 > 80 {print $6, $5}'
# переменная из оболочки
LIMIT=50; ps aux | awk -v l="$LIMIT" '$3 > l {print $2, $11, $3"%"}'Вывод можно форматировать через printf и менять разделитель на выходе переменной OFS. Приём $1=$1 заставляет awk пересобрать строку с новым разделителем:
awk -F: -v OFS=';' '{$1=$1; print}' /etc/passwd
awk '{printf "%-20s %10s\n", $1, $2}' sizes.txtДля CSV с запятыми внутри кавычек простого -F, мало. В gawk 5.3 и новее есть ключ --csv, который разбирает такие поля правильно (в Ubuntu 26.04 и Fedora 44 стоит 5.3.2, в Debian 13 версия 5.2.1, без этой опции).
Однострочники awk для логов и отчётов
# сумма пятого столбца (размеры в ls -l)
ls -l | awk '{s += $5} END {print s/1024/1024 " MiB"}'
# топ-10 IP в логе nginx
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head
# то же целиком на awk через массив
awk '{c[$1]++} END {for (ip in c) print c[ip], ip}' access.log | sort -rn | head
# коды ответов и их количество
awk '{print $9}' access.log | sort | uniq -c
# удалить повторяющиеся строки без сортировки
awk '!seen[$0]++' list.txt
# строки из file2, у которых первое поле есть в file1
awk 'NR==FNR {a[$1]; next} $1 in a' file1 file2
# заменить подстроку во всех строках
awk '{gsub(/foo/, "bar"); print}' file.txtПравку на месте умеет только gawk: gawk -i inplace '{gsub(/foo/, "bar")} 1' file.txt. В mawk делайте через временный файл: awk '...' file > file.tmp && mv file.tmp file. Направлять вывод сразу в исходный файл (> file) нельзя: оболочка обнулит его ещё до запуска awk. Однострочники удобно оформлять в функции или алиасы, как описано в статье про алиасы bash, а длинные цепочки выносить в bash-скрипты.
Почему sed или awk не находит совпадение
- Невидимые символы. Файл из Windows содержит
\rв конце строк, и шаблонvalue$не совпадает. Проверьтеcat -A file: в конце строк будет^M$. - Кавычки. Выражение sed и программа awk почти всегда пишутся в одинарных кавычках. В двойных оболочка заменит
$1и$NFна свои переменные, и awk получит пустоту. - BRE против ERE.
sed 's/a+/b/'ищет буквально "a+". Нужен-Eили\+. - Кириллица и регистр. Флаг
Iи классы вроде[[:upper:]]зависят от локали. В скриптах cron локаль может бытьC; задайтеLC_ALL=C.UTF-8явно. - Разделитель полей. По умолчанию awk схлопывает подряд идущие пробелы и табуляции, поэтому вывод
ls -lиpsделится правильно. С явным-F','или-F'\t'каждый разделитель значим: два подряд дадут пустое поле, и номера столбцов сдвинутся.
Полные описания команд есть в руководстве GNU sed и руководстве GNU awk.
Частые вопросы
Как заменить текст во всех файлах каталога?
Найдите файлы через grep -rlZ 'старое' каталог и передайте их в xargs -0 sed -i 's/старое/новое/g'. Перед этим проверьте замену без -i на одном файле.
Как заменить строку целиком по шаблону?
sed -i '/шаблон/c новая строка' файл. Или через замену всей строки: sed -i 's/^param=.*/param=value/' файл.
Как вывести определённый столбец?
awk '{print $3}' файл выводит третий столбец. Для другого разделителя укажите -F, например awk -F: '{print $1}' /etc/passwd.
Чем sed -i отличается от sed без ключей?
Без -i sed печатает результат в терминал и не меняет файл. С -i результат записывается в файл, с -i.bak рядом остаётся копия оригинала.
Почему awk -i inplace не работает в Ubuntu?
В Debian и Ubuntu по умолчанию стоит mawk, который этого не умеет. Установите gawk и вызывайте gawk -i inplace.
Документация и источники
Читайте также
- Поиск файлов в Linux: по имени, размеру, дате и содержимому
- Bash-скрипты для начинающих: от первого файла до рабочего бэкапа
- Aliases в Linux: псевдонимы команд, которые экономят время
- Основные команды Linux для начинающих с примерами
- Vim для начинающих: как выйти из редактора, сохранить файл и работать без мыши
- Cron и crontab в Linux: как настроить задания по расписанию
Команды проверены на актуальных версиях дистрибутивов на момент обновления. Перед изменением системных настроек сделайте резервную копию.