我似乎遇到了一个特定于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
Run Code Online (Sandbox Code Playgroud)
这是输出(请注意示例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.
Run Code Online (Sandbox Code Playgroud)
该'来"替代似乎出现之前运行该命令.在实际上下文中,heredoc将SQL传递给Oracle.通过更改'为",字符串将转换为标识符,从而打破SQL.在执行上述代码期间启用xtrace也可以观察到这一点.
我怎样才能防止'以"在上面的代码片断转换,而无需使用反引号?
编辑:情节变浓.$( ... )用反引号表示法替换命令替换不会用双引号替换单引号.那么(可选)问题二:为什么?
几年前我发现同样的错误时,这是我的笔记.
测试脚本:
#!/bin/ksh
cat <<EOF
$PWD "$PWD" '$PWD'
EOF
echo `cat <<EOF
$PWD "$PWD" '$PWD'
EOF
`
echo $(cat <<EOF
$PWD "$PWD" '$PWD'
EOF
)
Run Code Online (Sandbox Code Playgroud)
不同壳的输出:
(注意:按预期工作)
/home/jrw32982 "/home/jrw32982" '/home/jrw32982'
/home/jrw32982 "/home/jrw32982" '/home/jrw32982'
/home/jrw32982 "/home/jrw32982" '/home/jrw32982'
Run Code Online (Sandbox Code Playgroud)
(注意:单引号替换为双引号,变量未替换)
/home/jrw32982 "/home/jrw32982" '/home/jrw32982'
/home/jrw32982 "/home/jrw32982" '/home/jrw32982'
/home/jrw32982 "/home/jrw32982" "$PWD"
Run Code Online (Sandbox Code Playgroud)
解决方法:
从here-file外部计算单引号字符串
abc=xyz
STR="'$abc'"
x=$( cat <<EOF
$abc "$abc" $STR
EOF
)
Run Code Online (Sandbox Code Playgroud)在函数中使用here-file而不是直接使用
fn() {
cat <<EOF
$abc "$abc" '$abc'
EOF
}
abc=xyz
x=$(fn)
Run Code Online (Sandbox Code Playgroud)