sed? - 在带有特殊字符的字符串后面插入 Neutron 服务的行

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

TL;DR - 插入

--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

答案1

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分隔符可以使替换之前和之后的段不再那么纠缠。

答案2

您的问题不在于 被误解的任何字符,而是您在这种情况下选择部署的sed命令不正确。a追加a命令将文本放在所选行之后,而您需要的是在所选行内插入一些文本。为此,您需要该s///命令。

如果这是一次性的事情,那么您可以对替换进行硬编码,如 DopeGhoti 所示。但如果您想要“填完就忘记”类型的操作,那么您需要执行以下步骤:


  1. 定义您的搜索和替换字符串。
  2. 准备这些字符串的转义版本,这样无论它们包含什么,您都不需要再次摆弄 sed 命令。
  3. 使用转义字符串而不是原始字符串运行命令。

 # define strings
srch='--config-file /etc/neutron/plugin.ini'
repl='--config-file /etc/neutron/plugins/ml2/ml2_conf_cisco_apic.ini'

# generate their escaped versions
srch_esc=$(printf '%s\n' "$srch"  | sed -e 's|[][^\/.*$]|\\&|g')
repl_esc=$(printf '%s\n' "$repl"  | sed -e 's|[\&/]|\\&|g;$!s/$/\\/')

# run
sed -e '
   /^\[Service]/,/^$/!b
   /^ExecStart=/!b
   '"s/[[:space:]]${srch_esc}[[:space:]]/&${repl_esc} /"'
' yourfile

解释

  1. 选择您希望发生替换的适当范围,在您的情况下,它位于 [Service] ... 空行的行内。通过这样做,我们可以减少在不需要的区域进行更改的机会。
  2. 一旦进入范围,我们将感兴趣的行归零,在您的情况下,它位于以 ExecStart= 开头的行上。
  3. 在这里,我们只是使用转义变量而不是原始变量,并且我们退出单引号,进入双引号...放置数据...退出双引号,返回单引号。 (让引用宇宙快乐)

答案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

(&是匹配的字符串)

相关内容