无法理解sed模式

时间:2013-06-25 19:15:20

标签: bash loops sed block

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

############
# 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'之前添加'\',但现在它又给了我一个错误,它告诉我'\'是一个未知的命令。

有人可以解释我在上述问题上的错误以及此脚本的工作原理吗?

以下是我的理解:

-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

谢谢!

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

  • :a引入了一个名为a
  • 的标签
  • n将当前模式空间写入输出,并将模式空间替换为下一行输入。
  • /^$/!表示匹配模式空间中 NOT !)空行的行;当匹配(非空行)发生时,以下ba是“标记a的分支”。
  • 如果没有发生分支,则会发生i插入。

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

答案 2 :(得分:0)

在交互式shell中,!用于历史记录替换,因此您需要将其转义:

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

你也应该转义$,因为它在双引号字符串中有特殊含义(虽然在这种情况下它没关系,因为它后跟/,而不是变量名。)