sed? – Вставить строку после строки со специальными символами в сервисе Neutron

Вопрос или проблема

Я пытаюсь написать скрипт bash, который вставит строку после совпадения строки в

/usr/lib/systemd/system/neutron-server.service

Мне удалось сделать это на других файлах без проблем, так как я просто вставлял переменные в необходимые конфигурационные файлы, но этот файл, пох似, вызывает у меня затруднения.

Я полагаю, что ошибка в том, что sed не игнорирует специальные символы. В своей попытке я пробовал использовать одинарные и двойные кавычки в sed (что, как я понимаю, предназначено для переменных, но думал, что это может что-то изменить). Есть ли лучший способ решить эту задачу или какие-то специальные флаги или синтаксис sed, которые я упускаю?

sed ‘/--config-file /etc/neutron/plugin.ini/a\--config-file /etc/neutron/plugins/ml2/ml2_conf_cisco_apic.ini‘ /usr/lib/systemd/system/neutron-server

Кратко – вставить

--config-file /etc/neutron/plugins/ml2/ml2_conf_cisco_apic.ini 

После

--config-file /etc/neutron/plugin.ini

Оригинальный файл

[Unit]
Description=OpenStack Neutron Server
After=syslog.target network.target

[Service]
Type=notify
User=neutron
ExecStart=/usr/bin/neutron-server --config-file /usr/share/neutron/neutron-
dist.conf --config-dir /usr/share/neutron/server --config-file 
/etc/neutron/neutron.conf --config-file /etc/neutron/plugin.ini --config-dir 
/etc/neutron/conf.d/common --config-dir /etc/neutron/conf.d/neutron-server -
-log-file /var/log/neutron/server.log
PrivateTmp=true
NotifyAccess=all
KillMode=process
TimeoutStartSec="infinity"

[Install]
WantedBy=multi-user.target

Файл после выполнения нужной команды изменения.

[Unit]
Description=OpenStack Neutron Server
After=syslog.target network.target

[Service]
Type=notify
User=neutron
ExecStart=/usr/bin/neutron-server --config-file /usr/share/neutron/neutron-
dist.conf --config-dir /usr/share/neutron/server --config-file 
/etc/neutron/neutron.conf --config-file /etc/neutron/plugin.ini --config-
file /etc/neutron/plugins/ml2/ml2_conf_cisco_apic.ini --config-dir 
/etc/neutron/conf.d/common --config-dir /etc/neutron/conf.d/neutron-server -
-log-file /var/log/neutron/server.log
PrivateTmp=true
NotifyAccess=all
KillMode=process
TimeoutStartSec="infinity"

[Install]
WantedBy=multi-user.target

sed -i.bak 's_--config-file /etc/neutron/plugin.ini_& --config-file /etc/neutron/plugins/ml2/ml2_conf_cisco_apic.ini_' /usr/lib/systemd/system/neutron-server.service  

Оригинальный файл будет сохранен как neutron-server.service.bak. Просто найдите строку, после которой нужно вставить что-то, и замените ее на эту строку, за которой следует вставка. Использование _, а не / в качестве разделителя sed делает сегменты до и после замены гораздо менее запутанными.

Ваша проблема не в неправильной интерпретации символов sed, а в неправильной команде a, которую вы выбрали для применения в этой ситуации. Команда append a вставляет текст после выбранной строки, тогда как вам нужно вставить некоторый текст внутрь выбранной строки. Для этого вам нужна команда s///.

Если это разовое действие, то вы можете просто зафиксировать замену, как уже показал DopeGhoti. Но если вы хотите, чтобы это было “заполни и забудь”, тогда вам нужно выполнить следующие шаги:


  1. Определите ваши строки поиска и замены.
  2. Подготовьте экранированную версию этих строк, чтобы независимо от того, что они содержат, вам не нужно было снова вмешиваться в вашу команду sed.
  3. Запустите команду, используя экранированные строки вместо оригиналов.

 # определите строки
srch="--config-file /etc/neutron/plugin.ini"
repl="--config-file /etc/neutron/plugins/ml2/ml2_conf_cisco_apic.ini"

# создайте их экранированные версии
srch_esc=$(printf '%s\n' "$srch"  | sed -e 's|[][^\/.*$]|\\&|g')
repl_esc=$(printf '%s\n' "$repl"  | sed -e 's|[\&/]|\\&|g;$!s/$/\\/')

# выполняем
sed -e '
   /^\[Service]/,/^$/!b
   /^\ExecStart=/!b
   '"s/[[:space:]]${srch_esc}[[:space:]]/&${repl_esc} /"'
' yourfile

Объяснение

  1. Выберите соответствующий диапазон, в котором вы хотите, чтобы замена произошла, в вашем случае это строки между [Service] … пустая строка. Таким образом, мы снижаем вероятность внесения изменений в нежелательном месте.
  2. Оказавшись в диапазоне, мы сосредотачиваемся на строке интереса, в вашем случае это строка, начинающаяся с ExecStart=.
  3. Здесь мы просто используем экранированные переменные вместо оригиналов, а также выходим из одинарных кавычек, заходим в двойные кавычки … вставляем данные … выходим из двойных кавычек, возвращаемся обратно в одинарные кавычки. (чтобы все кавычки были в порядке)

Чтобы все было аккуратно, положите строку соответствия в переменную A, а строку вставки в переменную B:

$ A="--config-file /etc/neutron/plugin.ini"
$ B="--config-file /etc/neutron/plugins/ml2/ml2_conf_cisco_apic.ini"

Команда sed будет следующей:

$ sed "s/$A/& $B/" input_file

Но так как A и B содержат /, вам нужно использовать другой разделитель для sed:

$ sed  "s#$A#& $B#" input_file

(& это строка соответствия)

Ответ или решение

Отвечая на ваш вопрос о том, как вставить строку после определённой строки в файле /usr/lib/systemd/system/neutron-server.service, я рекомендую использовать команду sed с подходящим синтаксисом. Давайте разберемся шаг за шагом.

Пробелы и Экранирование Символов

Как вы уже заметили, специальные символы в sed могут воспрепятствовать правильному выполнению команды. В вашем случае строка, которую вы хотите вставить, содержит символы, которые могут вызвать ошибки. Чтобы избежать таких проблем, мы можем воспользоваться экранированием.

Шаги Для Вставки Строки

  1. Определение Исходной и Вставляемой Строк:
    Начнем с определения переменных для исходного и вставляемого значений:

    srch="--config-file /etc/neutron/plugin.ini"
    repl="--config-file /etc/neutron/plugins/ml2/ml2_conf_cisco_apic.ini"
  2. Экранирование Строк:
    Прежде чем использовать эти строки в sed, мы должны экранировать специальные символы:

    srch_esc=$(printf '%s\n' "$srch" | sed -e 's/[\/&]/\\&/g')
    repl_esc=$(printf '%s\n' "$repl" | sed -e 's/[\/&]/\\&/g')
  3. Использование sed для Выполнения Замены:
    Перейдём к самому sed:

    sed -i.bak "s/$srch_esc/& $repl_esc/" /usr/lib/systemd/system/neutron-server.service
    • Здесь флаг -i.bak создаст резервную копию файла перед изменениями.
    • Команда s/// используется для замены, где & представляет собой найденную строку.

Пояснение Команды

  • В первой части команды s/$srch_esc/& $repl_esc/ мы ищем строку, соответствующую переменной srch_esc, и заменяем её, добавляя к ней содержимое переменной repl_esc.
  • Символ & в строке замены обозначает то, что было найдено, а затем к нему добавляется строка для вставки.

Заключение

Следуя вышеизложенным шагам, вы сможете корректно вставить строку в нужное место в файле neutron-server.service. Проверяйте изменения, убедившись в правильности пути файла и содержимого, которое вы добавляете.

Если у вас возникнут какие-либо затруднения в процессе, не стесняйтесь обращаться за дополнительной помощью. Успехов в вашей работе с sed и настройкой OpenStack Neutron!

Оцените материал
Добавить комментарий

Капча загружается...