我的原始问题是能够在配置文件中的特定块的末尾添加一行。
############
# 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
谢谢!
答案 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
你也应该转义$
,因为它在双引号字符串中有特殊含义(虽然在这种情况下它没关系,因为它后跟/
,而不是变量名。)