ksh88将单引号更改为heredocs内的双引号?

Mr.*_*ama 9 shell aix ksh

我似乎遇到了一个特定于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也可以观察到这一点.

我怎样才能防止'"在上面的代码片断转换,而无需使用反引号?


编辑:情节变浓.$( ... )用反引号表示法替换命令替换不会用双引号替换单引号.那么(可选)问题二:为什么?

jrw*_*ica 6

几年前我发现同样的错误时,这是​​我的笔记.

测试脚本:

#!/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)

不同壳的输出:

  • Linux KSH版本M 1993-12-28 q
  • Linux Bash 3.00.15(1)

(注意:按预期工作)

 /home/jrw32982 "/home/jrw32982" '/home/jrw32982'
 /home/jrw32982 "/home/jrw32982" '/home/jrw32982'
 /home/jrw32982 "/home/jrw32982" '/home/jrw32982'
Run Code Online (Sandbox Code Playgroud)
  • AIX Version M-11/16/88f
  • Solaris版本M-11/16/88i

(注意:单引号替换为双引号,变量未替换)

 /home/jrw32982 "/home/jrw32982" '/home/jrw32982'
 /home/jrw32982 "/home/jrw32982" '/home/jrw32982'
 /home/jrw32982 "/home/jrw32982" "$PWD"
Run Code Online (Sandbox Code Playgroud)

解决方法:

  1. 从here-file外部计算单引号字符串

    abc=xyz
    STR="'$abc'"
    x=$( cat <<EOF
      $abc "$abc" $STR
    EOF
    )
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在函数中使用here-file而不是直接使用

    fn() {
      cat <<EOF
        $abc "$abc" '$abc'
    EOF
    }
    abc=xyz
    x=$(fn)
    
    Run Code Online (Sandbox Code Playgroud)