我正在尝试更新服务器上的一个文件,其中新行需要在前面有一个制表符,但是对于 bash 脚本和 sed 来说却是新手,并且在前面不断出现不需要的字符。
这是 sed 命令:
sed -i "/acl \"trusted\" {/a&\t$ACL_IP; # $SRV_HOST_NAME" $ACL_CONF_FILE
In the results I get :
& 192.12.12.12; # SERVER
192.13.13.13; # SERVER1
192.14.14.14; # SERVER2
Instead of :
192.12.12.12; # SERVER
192.13.13.13; # SERVER1
192.14.14.14; # SERVER2
我也尝试了以下操作但收到未知命令错误:
sed -i "/acl \"trusted\" {/$ACL_IP # $SRV_HOST_NAME;\r\n\tacl \"trusted\" {/" $ACL_CONF_FILE
我也尝试过:
sed -i "/acl \"trusted\" {/a/\t$ACL_IP; # $SRV_HOST_NAME" $ACL_CONF_FILE
但得到:
/ 192.12.12.12; # SERVER
希望我已经接近了,但就是看不到摆脱多余的角色。
答案1
因此,您正在尝试使用(GNU 扩展)a text
命令来Atext
匹配后附加。但是,在这种情况下,您的 以制表符开头,由转义序列text
表示。sed
\t
不幸的是,还有一种(符合 POSIX 标准的)形式A附加命令,其中反斜杠字符将a
命令与分开text
。因此,当您写入时,a\t
它会附加一个文字 t
&
。您可以通过放置一个额外的字符(首先是,然后是/
)将反斜杠与命令分开来“解决”该问题a
- 但这只会导致这些字符按字面意思附加。
为了解决歧义,您需要将命令传递为a\\t
。不幸的是,由于您在整个 sed 表达式周围使用了双引号(以允许扩展 shell 变量),因此 shell 将扩展\\
为\
;要传递,\\
您需要转义两个反斜杠:
sed "/acl \"trusted\" {/a\\\\t$ACL_IP; # $SRV_HOST_NAME"
或者,用单引号括住不需要 shell 扩展的部分:
sed '/acl "trusted" {/a\\t'"$ACL_IP; # $SRV_HOST_NAME"
\t
另一个选项是用文字制表符替换转义序列,使用Ctrl+ Vthen组成TAB。您仍然必须使用a\
命令的形式,因为 GNU 扩展a text
形式会忽略前导空格。
或者(也许更干净),您可以使用命令从标准输入r
读取格式化的字符串:printf
printf '\t%s; # %s\n' "$ACL_IP" "$SRV_HOST_NAME" |
sed -i '/acl "trusted" {/r/dev/stdin' "$ACL_CONF_FILE"