我在 bash 脚本中有一组 sed 替换,并且收到有关未终止的“s”命令的错误。 sed 行如下所示:
sed -n -e "s/TMPFOO1/$FOO1/" -e "s/TMPFOO2/$FOO2/" -e "s/TMPFOO3/$FOO3/" -e "s/TMPFOO4/$FOO4/" -e "s/TMPFOO5/$FOO5/" /home/foo/template > /home/foo/template/finishedresult
但出于某种原因,bash 不喜欢这个,我收到一个错误
sed: -e expression #4, char 69: unterminated `s' command
我在这里缺少什么?如何让 SED 输入变量?在我看来他们都被终止了。
答案1
您无法在 sed 命令中安全地插入变量,因为替换是由 shell 执行的,而不是由 sed 执行的。变量的值成为 sed 语法。例如,在 中"s/TMPFOO1/$FOO1/"
,如果$FOO1
包含换行符,这将导致类似于您观察到的语法错误。如果$FOO1
包含 a /
,则这将终止s
命令并可能导致错误或可能导致执行其他命令(如果后面的内容/
恰好是有效的 sed 语法)。
虽然您可以执行第一遍替换以FOO1
引用其特殊字符以包含在该 sed 命令中,但使用 awk 要简单得多。 awk 有变量的概念,以及用于设置变量初始值的命令行语法。
awk -v FOO1="$FOO1" -v FOO2="$FOO2" -v FOO3="$FOO3" -v FOO4="$FOO4" -v FOO5="$FOO5" '{
sub(/TMPFOO1/, FOO1);
sub(/TMPFOO2/, FOO2);
sub(/TMPFOO3/, FOO3);
sub(/TMPFOO4/, FOO4);
sub(/TMPFOO5/, FOO5);
print;
}' /home/foo/template > /home/foo/template/finishedresult
答案2
您的变量之一很可能$FOO
包含由 解释的特殊字符sed
。
我有另一个版本,sed
它会生成其他错误消息,但这里是类似问题的示例:
$ VAR=a
$ echo i | sed -e "s/i/"$VAR"/"
a
$ tmp> VAR=/
$ echo i | sed -e "s/i/"$VAR"/"
sed: 1: "s/i///
": bad flag in substitute command: '/'
在这种情况下,$VAR
包含一个被解释为sed
尾部斜杠的字符。
答案3
正如其他人在这里提到的,这取决于 FOO* 变量的内容。在您的情况下,使用sed
是错误的选择,因为它可能包含一些特殊字符。
看一眼这个链接并查看函数gsub_literal
由于gsub_literal
从 stdin 读取并写入 stdout,用法将是:
gsub_literal "$search" "$replace" < /home/foo/template > /home/foo/template/finishedresult
示例输出:
rany$ cat > foo.txt
a'
a'
rany$ gsub_literal a\' b < foo.txt
b
b
答案4
通过在命令中尝试添加反斜杠,该问题已为我解决sed 's/.../.../g'
。这个命令
sed 's/\"a/ä/g' input_file
给了我这个错误消息
sed:-e 表达式 #1,字符 9:未终止的“s”命令
当它作为 c-shell 脚本的一部分执行时,它仅对最新版本的 执行此操作sed
,而不是对旧版本执行此操作。 (奇怪的是,当在命令行(在 tc-shell 中)给出相同的命令时,它可以正常工作)。
c-shell 脚本的问题已通过在字符前添加ä
反斜杠来解决:
sed 's/\"a/\ä/g' input_file