ksh - 在命令替换机制中使用变量

时间:2018-04-24 05:41:43

标签: bash shell sqlplus ksh heredoc

我不熟悉Linux中的脚本,我觉得我对在命令替换中使用变量感到困惑,我学习和阅读的内容越多。有人可以向我解释以下情况吗?

在我的ksh脚本中,我试图在sqlplus脚本中使用ksh变量,如下所示:

temp_var="'a', 'b'" 
randomVar=$(sqlplus -s $con_details <<EOF

update table ABC 
Set field1='val' 
Where field2 NOT IN ("${temp_var}");
EOF)

但是上面的语法导致查询出错,并且代码1失败。

然而,当我取消引用该变量并简单地写

Where field2 NOT IN (${temp_var});

查询运行正常。我在SO和Unix上看过很多例子,Linux建议总是引用你在命令替换中使用的变量,但对我来说似乎相反。

我似乎不明白为什么在$()中使用引号会给出错误,而不是使用它们。

此外,当我不在其中使用ksh变量时(即没有WHERE子句),查询运行正常。

1 个答案:

答案 0 :(得分:4)

这与通常的建议适用的情况不同 - 您在here-document中使用变量,而不是在命令行中使用变量。区别在于如何解析它。

当您在命令行上使用变量(类似ls $file)时,变量会在解析命令的过程中被其值中断,并带有奇怪且通常不合需要的结果。标准解决方案是双引号变量(ls "$file")以防止它被解析,只是直接使用。人们犯的标准错误就是在变量的值中加上引号,因为在引号已被解析后,变量被替换为,因此不起作用。

但是你在here-document中使用变量,那些工作的方式有很大不同。发生的事情是shell只是在here-document中进行变量扩展(以及一些转义解析),但不进行任何更广泛的解析。特别是,它不解析here-document中的引号,只是将它们视为任何其他字符。然后,该文档作为输入传递给命令(在您的情况下为sqlplus), it 根据其语法规则解析文档。由于解析发生在变量替换之后,引号是在变量中还是在变量周围并不重要;他们的工作方式相同。但你不能两者兼顾,这就是变量周围的双引号所发生的事情。基本上,您将此文档发送到sqlplus

update table ABC 
Set field1='val' 
Where field2 NOT IN ("'a', 'b'");

... sqlplus不喜欢单引号附近的双引号,并抱怨。