这是设置,我有两个变量:
$ echo "${ORIGINALSTRING}"
placeholdertext
$ echo "${REPLACEMENTSTRING}"
-----BEGIN CERTIFICATE-----
thisisarandombase64encodedstring
blahblahblahblahblahblahblahblah
blahblahblahblahblahblahblahblah
blahblahblahblahblahblahblahblah
blahblahblahblahblahblahblahblah
-----END CERTIFICATE-----
我需要将文本文件中存在的原始字符串替换为包含多行的字符串。我遇到了sed
:的死胡同
$ sed -i "s/${ORIGINALSTRING}/${REPLACEMENTSTRING}/g" ./somedir/file.txt
sed: -e expression #1, char 48: unterminated `s' command
我在同一个命令上尝试了二十多种变体,但最终我发现这是由一个有多行的环境变量引起的。因此,遗憾的是,sed
已退出。
有人对如何完成这项任务有其他想法吗?我听说awk
可以做我想做的事情,但我还没有看到任何与我的特定用例相关的好例子。
ORIGINALSTRING="$ORIGINALSTRING" REPLACEMENTSTRING="$REPLACEMENTSTRING" awk '
BEGIN {
old = ENVIRON["ORIGINALSTRING"]
new = ENVIRON["REPLACEMENTSTRING"]
}
s = index($0,old) {
$0 = substr($0,1,s-1) new substr($0,s+length(old))
}
{ print }
' file
无论shell变量中有什么字符,以上都会起作用,因为它正在使用文本字符串进行搜索和替换,而如果其中一个或另一个中存在/
、&
、1
、.
、*
、^
、$
或各种其他字符,则sed解决方案将失败,因为sed没有使用文本字符串的功能,请参阅是否可以使用sed可靠地转义regex元字符。
我几乎总是建议使用ed
来edit文件,而不是尝试使用非标准的sed -i
:
printf "%sn" "g/$ORIGINALSTRING/c" "$REPLACEMENTSTRING" . w | ed -s input.txt
这c会将与ORIGINALSTRING
匹配的每一行更改为REPLACEMENTSTRING
中的行(.
表示插入模式的输入结束(,并且w将更改后的文件重新格式化回磁盘。
sed
中的等效项需要在除最后一行之外的每一行末尾添加一个\
:
sed -i "/$originalstring/c\
${replacementstring//$'n'/\$'n'}" input.txt
另请参阅正确的bash和shell脚本变量大小写,并考虑是否应该使用所有大写的变量名。
用sed和bash的多行字符串替换字符串及其参数扩展:
ORIGINALSTRING='placeholdertext'
REPLACEMENTSTRING='-----BEGIN CERTIFICATE-----
thisisarandombase64encodedstring
blahblahblahblahblahblahblahblah
blahblahblahblahblahblahblahblah
blahblahblahblahblahblahblahblah
blahblahblahblahblahblahblahblah
-----END CERTIFICATE-----'
sed -i "s|${ORIGINALSTRING}|${REPLACEMENTSTRING//$'n'/\n}|" file
我从s///
切换到s|||
。