Команда sed: замена строк, удаление строк и использование опции -i
Команда sed — это инструмент Linux, который читает файл строка за строкой и выполняет замену, удаление и вставку, поэтому вы можете менять значения в файле конфигурации, не открывая редактор. Когда мы запустили sed для копии файла wp-config.php WordPress на сервере AlmaLinux 9, удалось изменить имя базы данных, сохранив оригинал с помощью -i.bak.
Сообщения об ошибках в этой статье приведены точно в том виде, в каком они вышли при английской locale.
1️⃣ Основы команды sed и замена через s
Самая востребованная команда s заменяет строки в формате [s/искомая строка/новая строка/]. В строке заменяется только первое совпадение.
echo 'http://example.com http://example.com/blog' | sed 's/http:/https:/'https://example.com http://example.com/blogЧтобы заменить все совпадения в строке, добавьте в конец флаг g.
echo 'http://example.com http://example.com/blog' | sed 's/http:/https:/g'https://example.com https://example.com/blogЕсли добавить в конец имя файла, sed прочитает этот файл и выведет изменённый результат. В копии wp-config-sample.php из WordPress под именем wp-config.php мы изменили значение DB_USER и проверили только эту строку через grep.
sed 's/username_here/wp_user/' wp-config.php | grep DB_USERdefine( 'DB_USER', 'wp_user' );Раз значение в выводе изменилось, легко решить, что изменился и файл, но без опций sed только выводит результат на экран и оставляет исходный файл как есть. Когда мы снова нашли ту же строку в файле, в ней осталось первоначальное значение.
grep DB_USER wp-config.phpdefine( 'DB_USER', 'username_here' );Чтобы изменить и исходный файл, используйте опцию -i из раздела 4️⃣.
2️⃣ Выбор строк в sed по номеру и шаблону (-n, p)
Без адреса команда s применяется ко всем строкам, поэтому для работы с отдельными строками укажите перед командой номер строки или шаблон как адрес. -n отключает автоматический вывод, а p выводит выбранные строки. Вместе они показывают только строку 23.
sed -n '23p' wp-config.phpdefine( 'DB_NAME', 'database_name_here' );Два номера строк через запятую дают этот диапазон. Строки с 23 по 32 — это раздел с настройками имени базы данных, пользователя, пароля и хоста.
sed -n '23,32p' wp-config.phpdefine( 'DB_NAME', 'database_name_here' );
/** Database username */
define( 'DB_USER', 'username_here' );
/** Database password */
define( 'DB_PASSWORD', 'password_here' );
/** Database hostname */
define( 'DB_HOST', 'localhost' );Если вместо номера строки написать шаблон между косыми чертами, будут выбраны все строки с этим шаблоном.
sed -n '/DB_/p' wp-config.phpdefine( 'DB_NAME', 'database_name_here' );
define( 'DB_USER', 'username_here' );
define( 'DB_PASSWORD', 'password_here' );
define( 'DB_HOST', 'localhost' );
define( 'DB_CHARSET', 'utf8mb4' );
define( 'DB_COLLATE', '' );Команда [=] выводит номер выбранной строки. Адрес $ означает последнюю строку, поэтому через [$=] можно узнать общее число строк файла.
sed -n '/DB_HOST/=' wp-config.php32sed -n '$=' wp-config.php102Адрес можно поставить и перед командой s. Ниже результат замены localhost только в строке 32 с выводом лишь изменённой строки через флаг p.
sed -n '32s/localhost/127.0.0.1/p' wp-config.phpdefine( 'DB_HOST', '127.0.0.1' );При запуске p без -n выбранная строка появилась ещё раз. sed читает строки по одной в пространство шаблона, выполняет команды, а затем автоматически выводит пространство шаблона, поэтому строка 2, выведенная через p, снова появляется при автоматическом выводе.
sed '2p' wp-config.php | head -n 4<?php
/**
/**
* The base configuration for WordPressТакая обработка по одной строке похожа на заводской конвейер, который подаёт детали по одной на рабочий стол, обрабатывает их и переходит к следующей.
На схеме ниже можно по шагам сравнить, что выводит каждая команда для каждой строки.
3️⃣ Удаление и вставка строк командой sed (d, i, a)
d удаляет выбранные строки. Чтобы увидеть пример настройки nginx ниже без строк комментариев, выберите шаблоном [^ *#] строки, которые начинаются с # или содержат перед # только пробелы.
cat example.conf# example.com
server {
listen 80;
server_name example.com www.example.com;
# document root
root /var/www/example.com;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$args;
}
}sed '/^ *#/d' example.confserver {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$args;
}
}Если соединить команды точкой с запятой, удаляется и [^$], что означает пустую строку. Две пустые строки, оставшиеся после удаления комментариев, исчезли, и остались только строки настроек.
sed '/^ *#/d; /^$/d' example.confserver {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$args;
}
}i вставляет текст перед выбранной строкой, а a после неё. Результат вставки одной строки комментария перед строкой 1 показан ниже.
sed '1i # managed by sed' example.conf | head -n 3# managed by sed
# example.com
server {Легко решить, что текст с отступом после a вставится вместе с отступом, но GNU sed пропускает пробелы сразу после a и вставляет только текст.
sed '/index index.php/a client_max_body_size 64M;' example.conf# example.com
server {
listen 80;
server_name example.com www.example.com;
# document root
root /var/www/example.com;
index index.php index.html;
client_max_body_size 64M;
location / {
try_files $uri $uri/ /index.php?$args;
}
}Чтобы сохранить отступ, добавьте после a обратную косую черту. Всё начиная с пробела после неё попадает в текст.
sed '/index index.php/a\ client_max_body_size 64M;' example.conf# example.com
server {
listen 80;
server_name example.com www.example.com;
# document root
root /var/www/example.com;
index index.php index.html;
client_max_body_size 64M;
location / {
try_files $uri $uri/ /index.php?$args;
}
}c заменяет выбранную строку целиком. Ниже первые четыре строки результата замены строки listen 80 на 8080.
sed '/listen 80;/c\ listen 8080;' example.conf | head -n 4# example.com
server {
listen 8080;
server_name example.com www.example.com;4️⃣ Прямое изменение файлов через sed -i и имя резервной копии
-i сохраняет результат в исходный файл, а не выводит на экран. Текст сразу после -i добавляется в конец имени резервной копии. wp-config.php и другие файлы, которые читает сайт, лучше редактировать с -i.bak, сохраняя оригинал.
cp wp-config-sample.php wp-config.phpsed -i.bak 's/database_name_here/wordpress_db/' wp-config.phpС -i на экран ничего не выводится, поэтому проверьте файлы через ls -l.
ls -l wp-config.php*-rw-r--r-- 1 root root 3333 Oct 28 15:13 wp-config.php
-rw-r--r-- 1 root root 3339 Oct 28 15:13 wp-config.php.bakРядом появились отредактированный файл и файл .bak. Размер уменьшился на 6 байт, потому что database_name_here сократилось до wordpress_db. Сравнение двух файлов через diff показывает только изменённую строку.
diff wp-config.php.bak wp-config.php23c23
< define( 'DB_NAME', 'database_name_here' );
---
> define( 'DB_NAME', 'wordpress_db' );Изменилась одна строка DB_NAME в строке 23.
Если нужно изменить несколько значений, свяжите скрипты через -e и выполните их за один раз.
sed -i -e 's/username_here/wp_user/' -e 's/password_here/wp_pass/' wp-config.phpgrep -n -e DB_USER -e DB_PASSWORD wp-config.php26:define( 'DB_USER', 'wp_user' );
29:define( 'DB_PASSWORD', 'wp_pass' );Если написать -i и -e слитно как [-ie], буква e читается как часть имени копии, и, как показано ниже, появился файл wp-config.phpe.
sed -ie 's/127.0.0.1/localhost/' wp-config.phpls wp-config.php*wp-config.php
wp-config.php.bak
wp-config.phpe-i записывает изменённое содержимое в новый файл, а затем переименовывает его в исходное имя, поэтому номер inode файла до и после запуска различается.
ls -i wp-config.php207618887 wp-config.phpsed -i 's/localhost/127.0.0.1/' wp-config.phpls -i wp-config.php207618883 wp-config.phpНомер inode, бывший 207618887 до запуска, сменился на 207618883.
Если файла нет или имя файла пропущено, sed завершается ошибкой ниже и ни один файл не меняется.
sed -i 's/x/y/' no-such.phpsed: can't read no-such.php: No such file or directorysed -i 's/x/y/'sed: no input files5️⃣ Регулярные выражения sed, смена разделителя и опции
🔲 Регулярные выражения и смена разделителя
Если менять значение с косыми чертами, например путь, разделитель команды s смешивается с косыми чертами значения, поэтому перед каждой косой чертой в значении нужна обратная косая черта.
sed -n 's/\/var\/www\/example.com/\/srv\/www\/example.com/p' example.conf root /srv/www/example.com;Символ сразу после s становится разделителем, поэтому если перейти на |, которого нет в значении, тот же результат получится без обратных косых черт.
sed -n 's|/var/www/example.com|/srv/www/example.com|p' example.conf root /srv/www/example.com;Точка (.) в шаблоне соответствует любому одному символу. Ниже результат шаблона для example.com, который изменил и exampleXcom.
echo 'exampleXcom example.com' | sed 's/example.com/test.org/g'test.org test.orgЧтобы искать точку как символ, поставьте перед ней обратную косую черту.
echo 'exampleXcom example.com' | sed 's/example\.com/test.org/g'exampleXcom test.orgЧасть в скобках вызывается в новой строке через [\1]. С -E скобки и + используются без обратных косых черт. Ниже результат, где число после listen осталось, а default_server добавлено.
sed -nE 's/listen ([0-9]+);/listen \1 default_server;/p' example.conf listen 80 default_server;Без -E тот же скрипт читает скобки как текст, и появляется ошибка, что нет группы для вызова. Чтобы работать без -E, ставьте обратную косую черту перед скобками и +.
sed -n 's/listen ([0-9]+);/listen \1 default_server;/p' example.confsed: -e expression #1, char 46: invalid reference \1 on `s' command's RHSsed -n 's/listen \([0-9]\+\);/listen \1 default_server;/p' example.conf listen 80 default_server;[&] в новой строке означает весь текст, совпавший с шаблоном, поэтому перед совпавшей частью можно добавить # и превратить строку в комментарий.
sed -n 's/server_name .*;/# &/p' example.conf # server_name example.com www.example.com;🔲 Опции команды sed
📌 Основные опции: результаты из этой статьи
| Опция | Назначение | Результат в этой статье | |
|---|---|---|---|
| -n | Отключает автоматический вывод и выводит только строки, выбранные через p | sed -n '23p' показывает только строку 23; без -n 2p выводит строку 2 дважды | |
| -i | Сохраняет результат в исходный файл вместо экрана (текст сразу после опции идёт в конец имени копии) | -i.bak создаёт wp-config.php.bak; после запуска меняется номер inode | |
| -e | Связывает несколько скриптов и выполняет их за один раз | DB_USER и DB_PASSWORD меняются за один раз; при слитном -ie появляется копия wp-config.phpe | |
| -E | Использует расширенные регулярные выражения (без обратной косой черты у скобок и +) | Выводит listen 80 default_server;; тот же скрипт без -E даёт ошибку [invalid reference] | |
| --follow-symlinks | Вместе с -i редактирует исходный файл, на который указывает ссылка | Без неё на месте ссылки появляется обычный файл, а оригинал не меняется; с ней меняется исходное значение |
📎 Другие опции: по официальному руководству
| Опция | Назначение | |
|---|---|---|
| -f | Читает скрипт из файла и выполняет его | |
| -r | Расширенные регулярные выражения, как -E (переносимее -E) | |
| -s | Обрабатывает файлы по отдельности, а не как один непрерывный поток | |
| -z | Разделяет строки нулевым символом вместо перевода строки | |
| -u | Читает ввод меньшими порциями и чаще сбрасывает вывод | |
| --posix | Отключает все расширения GNU | |
| --debug | Выводит ход выполнения в развёрнутом виде |
🔲 Симулятор команды sed
В рабочей папке симулятора ниже есть копия wp-config.php и example.conf. Вы можете сами вводить изученные команды, а файлы, изменённые через -i, проверять через ls -l и diff.
🔢 FAQ & рекомендуемые материалы







ℹ️ О партнёрских ссылках
Материалы этого сайта содержат партнёрские ссылки. Если посетитель покупает товар или услугу по такой ссылке, сайт получает комиссию от продавца. При этом сумма, которую платит покупатель (при акционных скидках сумма снижается ↓), не увеличивается. Указанные цены, скидки и наличие актуальны на момент написания и могут отличаться, поэтому перед покупкой уточняйте их у продавца. Товары выбираются и оцениваются по нашим собственным критериям, а комиссия не влияет ни на порядок, ни на содержание обзоров.