sed 重复流中的最后一行

sed 重复流中的最后一行

我的脚本中有与此类似的代码...

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 将尝试调用该命令。sedFailed

一些建议:

  1. 删除字符类(外括号)
  2. 删除前导.*,这将删除前导注释等。
  3. sed运行包含多个语句的单个命令
  4. 修复错误情况消息


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]

删除外括号会删除字符类,因此表达式将与提供的确切子字符串匹配。

相关内容