我正在尝试编写一个 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 所示。但如果您想要“填完就忘记”类型的操作,那么您需要执行以下步骤:
- 定义您的搜索和替换字符串。
- 准备这些字符串的转义版本,这样无论它们包含什么,您都不需要再次摆弄 sed 命令。
- 使用转义字符串而不是原始字符串运行命令。
# 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
解释
- 选择您希望发生替换的适当范围,在您的情况下,它位于 [Service] ... 空行的行内。通过这样做,我们可以减少在不需要的区域进行更改的机会。
- 一旦进入范围,我们将感兴趣的行归零,在您的情况下,它位于以 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
(&是匹配的字符串)