我似乎遇到了一个特定于ksh88的问题,它将单引号改为双引号,但仅限于涉及heredocs和命令替换的某些情况。
以下是一个例子:
#!/bin/ksh
# This example works correctly
echo "Example 1:"
cat <<EOF
The 'quick' brown fox "jumped" over the lazy dog.
EOF
echo
# This example is broken
echo "Example 2:"
var=$(cat <<EOF
The 'quick' brown fox "jumped" over the lazy dog.
EOF)
echo "${var}"
echo
# This example works correctly
echo "Example 3:"
var=`cat <<EOF
The 'quick' brown fox "jumped" over the lazy dog.
EOF`
echo "${var}"
echo
这是输出(注意示例2的不同之处):
Example 1:
The 'quick' brown fox "jumped" over the lazy dog.
Example 2:
The "quick" brown fox "jumped" over the lazy dog.
Example 3:
The 'quick' brown fox "jumped" over the lazy dog.
在命令运行之前,'
到"
替换似乎发生。在实际上下文中,heredoc将SQL传递给Oracle。通过将'
更改为"
,字符串将转换为标识符,从而破坏SQL。在执行上述代码期间启用xtrace也可以观察到这一点。
如何在不使用反引号的情况下阻止上述代码段中的'
到"
转换?
编辑:情节变浓。用反引号表示法替换命令替换$( ... )
并不能用双引号替换单引号。那么(可选)问题二:为什么?
答案 0 :(得分:6)
几年前,当我发现同样的错误时,这是我的笔记。
测试脚本:
#!/bin/ksh
cat <<EOF
$PWD "$PWD" '$PWD'
EOF
echo `cat <<EOF
$PWD "$PWD" '$PWD'
EOF
`
echo $(cat <<EOF
$PWD "$PWD" '$PWD'
EOF
)
不同炮弹的输出:
(注意:按预期工作)
/home/jrw32982 "/home/jrw32982" '/home/jrw32982'
/home/jrw32982 "/home/jrw32982" '/home/jrw32982'
/home/jrw32982 "/home/jrw32982" '/home/jrw32982'
(注意:单引号替换为双引号,变量未替换)
/home/jrw32982 "/home/jrw32982" '/home/jrw32982'
/home/jrw32982 "/home/jrw32982" '/home/jrw32982'
/home/jrw32982 "/home/jrw32982" "$PWD"
解决方法:
从here-file
外部计算单引号字符串abc=xyz
STR="'$abc'"
x=$( cat <<EOF
$abc "$abc" $STR
EOF
)
在函数中使用here-file而不是直接
fn() {
cat <<EOF
$abc "$abc" '$abc'
EOF
}
abc=xyz
x=$(fn)