sed为什么给我一个关于未终止的s的错误?


9

我在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输入变量?在我看来,他们都被解雇了。


2
$ FOO4包含使sed s命令未终止的奇怪内容(例如:“ \”或“ \\”?)。(这就是为什么我认为它是结尾的“ \”,使下一个“ /”被视为替换字符串的字符部分,而不是s命令的终止字符)
Olivier Dulac

Answers:


7

您不能在sed命令中安全地插入变量,因为替换是由Shell而不是sed执行的。变量的值成为sed语法。例如,在中"s/TMPFOO1/$FOO1/",如果$FOO1包含换行符,这将导致语法错误,如您观察到的那样。如果$FOO1包含/,这将终止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

重要说明:-a -v必须在每个变量声明之前。
Mike B

@MikeB感谢您的错误报告。通常,当您发现这样的错字时,请直接编辑该帖子。
吉尔(Gilles)'所以

@Gilles来自非作者的编辑必须至少包含六个字符。
NobleUplift

6

您的$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为尾部斜杠。


2

就像其他人在这里提到的那样,它取决于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

1

通过在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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.