-1

我最初的问题是能够在配置文件中特定块的末尾添加一行。

############
# MY BLOCK #
############
VALUE1 = XXXXX
VALUE2 = YYYYY
MYNEWVALUE = XXXXX      <<< I want to add this one

##############
# MY BLOCK 2 #
##############

为此,我使用了以下 sed 脚本,它可以完美运行(在另一篇文章中找到):

sed -i -e "/# MY BLOCK #/{:a;n;/^$/!ba;i\MYNEWVALUE = XXXXX" -e '}' myfile

这在 shell 脚本中执行时效果很好,但我无法直接在交互式 shell 中使用它(它给了我一个错误:“!ba event not found”)。为了解决这个问题,我尝试在 '!ba' 之前添加 '\' 但现在它给了我另一个错误,告诉我 '\' 是一个未知命令。

谁能解释我在上述问题上的错误在哪里以及这个脚本是如何工作的?

以下是我的理解:

-i : insert new line (i think the first one is useless, am i right?)
-e : execute this sed script (don't understand why there is a second one at the end to close the })
:a : begin a loop
n : read each line with the pattern ^$ (empty lines)
! : reverse the loop
ba : end of the loop

谢谢 !

4

3 回答 3

1

使用'而不是"避免让 bash 尝试在!

如果XXXXX包含 shell 参数扩展或类似的,你可以这样做:

sed -i -e"/# $BLOCK_NAME"'#/{:a;n;/^$/!ba;i\'"$NEW_VAR = $NEW_VALUE" -e"}" myfile

第二个-e需要有效地插入换行符以关闭i命令。您实际上可以直接插入换行符,而不是:

sed -i -e"/# $BLOCK_NAME "'#/{:a;n;/^$/!ba;i\'"$NEW_VAR = $NEW_VALUE"$'\n}' myfile
于 2013-06-25T19:26:36.183 回答
0

在交互式 shell 中,!用于历史替换,因此您需要对其进行转义:

sed -i -e "/# MY BLOCK #/{:a;n;/^\$/\!ba;i\MYNEWVALUE = XXXXX" -e '}' myfile

您还应该转义$,因为它在双引号字符串中具有特殊含义(尽管在这种情况下它是可以的,因为它后面跟着/,而不是变量名)。

于 2013-06-25T19:35:24.317 回答
0
  • :a引入了一个名为 的标签a
  • n将当前模式空间写入输出,并用下一行输入替换模式空间。
  • /^$/!表示匹配模式空间中不是( !) 空行的行;当匹配(不是空行)发生时,以下ba是“标记 a 的分支”。
  • 如果分支没有发生,则i插入发生。

在命令行中使用单引号 (') 而不是双引号 (") 以防止 shell 执行 shell 替换(包括 "$" 和 "!" 字符)。

于 2013-06-25T19:34:08.527 回答