Sed эта мощная утилита, которая позволяет обрабатывать текст, здесь же описано изменение строки в конфиге с помощью sed.
Введение
Когда требуется поправить какой-нибудь конфиг, мы можем сделать это с помощью какого-нибудь редактора, например nano. Но иногда хочется чтобы конфиг менялся по команде, например из скрипта, или из подготовленной инструкции. Это возможно сделать с помощью утилиты sed.
Утилита sed позволяет производить фильтрацию, поиск, замену, вставку и удаление строк или частей текста в файлах или потоках данных. Вот несколько примеров её работы.
- Редактирование строк с помощью регулярных выражений, но без редактирования самого файла. Замена производится с помощью команды
s
, мы говорим что и на что меняем.
# sed 's/old/new/' file.txt
- Предыдущая команда не редактирует файл. Внесение изменений непосредственно в файл производится с помощью опции
-i
.
# sed -i 's/old/new/' file.txt
- Поиск и удаление определённых строк, подпадающих под шаблон выполняется с помощью команды
d
.
# sed '/pattern/d' file.txt
- Добавление строки после строки, попадающей под шаблон (pattern) выполняется с помощью команды
a
.
# sed '/pattern/a\New line' file.txt
- Также есть возможность выполнять несколько команд через опцию
-e
. Например заменим строки (s
) и удалим строки (d
).
sed -e 's/foo/bar/' -e '/baz/d' file.txt
Нашей задачей будет поиск и изменение строки в конфиге, то есть значения определённого параметра, с помощью утилиты sed. Делается это примерно так:
# sed -i '/pattern/s/old/new/' example.conf
То есть мы редактируем файл (используем опцию -i
). Находим строку по pattern и в строке меняем (команда s
) old на new. И вместо строк мы можем использовать регулярные выражения.
Практика
Для начала придумаем тестовый конфиг, например такой:
$ cat <<EOT > example.conf parameter_1 = 10 parameter_2 = 13 parameter_3 = 133 parameter_4 = 58 parameter_5 = 38 EOT
Теперь с помощью sed закомментируем parameter_3:
$ sed -i '/^parameter_3 =/s/^/# /' example.conf $ cat example.conf parameter_1 = 10 parameter_2 = 13 # parameter_3 = 133 parameter_4 = 58 parameter_5 = 38
А чтобы снять комментарий, сделаем так:
$ sed -i '/^# parameter_3 =/s/^# //' example.conf $ cat example.conf parameter_1 = 10 parameter_2 = 13 parameter_3 = 133 parameter_4 = 58 parameter_5 = 38
А если мы не знаем, закомментирована строка или нет, а нам нужно в любом случае снять комментарий и выставить значение. Это тоже можно сделать. Для начала вернём комментарий, а затем выполним замену.
$ sed -i '/^parameter_3 =/s/^/# /' example.conf $ cat example.conf parameter_1 = 10 parameter_2 = 13 # parameter_3 = 133 parameter_4 = 58 parameter_5 = 38 $ sed -i '/^#\? parameter_3/s/.*/parameter_3 = 199/' example.conf $ cat example.conf parameter_1 = 10 parameter_2 = 13 parameter_3 = 199 parameter_4 = 58 parameter_5 = 38
В регулярном выражении ^#\?
означает что символ решётки не обязателен.
В комментарии мне подсказали как снять комментарий и выставить значение (если мы не знаем закомментирована ли была строчка или нет.)
$ sed -i '/parameter_3/c parameter_3 = 205' example.conf
Здесь используется команда c
(change), которая заменяет всю строку целиком. В отличии от команды s
(substitute), которая заменяет только подстроку соответствующую шаблону. То есть мы находим все строки по шаблону parameter_3
и заменяем их все на parameter_3 = 205
.
Это всё я проделывал на тестовом конфиге, важно протестировать своё решение перед реальным изменением, для этого вначале выполняйте команды без опции -i
. И только если вы уверены в своё решении, то можете писать скрипт или инструкцию с использованием sed -i
.
Другие статьи по программированию на bash вы найдёте здесь.
Если понравилась статья, подпишись на мой канал в VK или Telegram.
Снять комментарий в любом случае можно проще — заменить строку на новую по шаблону:
sed -i ‘/parameter_3/c parameter_3 = 199’ example.conf
Да, всё верно, спасибо за дополнение, попозже внесу это в статью
А как применить команду только к незакомментированной строке?
Т.к. меняются и описания с примерами:
# … text
# … you can set parameter_3=example for …
# … text
parameter_3=value1
замена применится к обеим строкам и в конфиге будет две одинаковые строки
# … text
parameter_3=value2
# … text
parameter_3=value2
в качестве костыля пока просто добавил якорь $ sed -i ‘/^parameter_3/c parameter_3 = 205’ example.conf
зная, точно формат своего конфига