我的脚本中有与此类似的代码...
smbconffile="/etc/samba/smb.conf"
sed -i 's/.*[\[CMI\]]/\[CMI\$\]/' $smbconffile && echo "Success" || "Failed"
sed -i 's/.*[\[LOCAL\]]/\[LOCAL\$\]/' $smbconffile && echo "Success" || "Failed"
sed -i 's/.*[\[NATIONAL\]]/\[NATIONAL\$\]/' $smbconffile && echo "Success" || "Failed"
这会将 samba conf (smb.conf) 中的共享名称更改为 CMI$、LOCAL$、NATIONAL$。
我遇到的问题是,在第二个 sed 命令之后,sed 找到“NATIONAL”,但它将其重命名为“LOCAL$”而不是“NATIONAL$”。有人发现命令有问题吗?任何帮助将不胜感激。
答案1
您将字符类(方括号内的字符列表)与由方括号文字包围的 smb.conf 共享名混合。此外,该命令的格式不正确:在以非零状态退出的echo
情况下,shell 将尝试调用该命令。sed
Failed
一些建议:
- 删除字符类(外括号)
- 删除前导
.*
,这将删除前导注释等。 sed
运行包含多个语句的单个命令- 修复错误情况消息
sed -i 's/\[CMI\]/\[CMI\$\]/;
s/\[LOCAL\]/\[LOCAL\$\]/;
s/\[NATIONAL\]/\[NATIONAL\$\]/' $smbconffile && echo "Success" || echo "Failed"`
您可以使用反向引用来避免在替换表达式中重新键入原始前缀(例如“[CMI”),但这会使表达式更难以阅读。
另一个建议是使用 Perl,它具有可读的分组和反向引用(IMO):
perl -pi -e 's/(\[(?:CMI|LOCAL|NATIONAL))\]/$1\$]/g' $smbconffile \
&& echo "Success" || echo "Failed"
编辑:为了澄清,带有外括号的原始表达式的问题在于,您正在创建一个字符类,该字符类与包含(在第一种情况下)[
, C
, M
, I
,的任何字符串(在第一种情况下)]
以任意顺序后跟]
.例如:
$ echo '[IMC]' | sed 's/[\[CMI\]]/[something_else]/'
[IM[something_else]
$ echo '[FOOM]' | sed 's/[\[CMI\]]/[something_else]/'
[FOO[something_else]
删除外括号会删除字符类,因此表达式将与提供的确切子字符串匹配。