2014-08-29 94 views
9

我似乎遇到了特定于ksh88的问题,该问题将单引号更改为双引号,但仅限于涉及heredocs和命令替换的某些情况。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来观察。

如何防止上述代码段中的'"转换不使用反引号?


编辑:情节复杂。用反引号替换命令替换$(...)不能用双引号替换单引号。所以(可选)问题二:为什么?

+3

描述的行为听起来像一个错误。改变back-ticks到'$(...)'不应该改变输出的内容。你能不能升级到['ksh93'](http://www.kornshell.com/)? – 2014-08-29 14:13:28

+0

@JonathanLeffler - 如果它是一个bug,它看起来很有意思。至于切换到ksh93,这不一定是一种选择。实际脚本需要在不同版本的多个AIX和Solaris服务器上运行。有几个有ksh93,但大多数只有ksh88。在上述所有情况下, – 2014-08-29 14:27:01

+0

@AdrianFrühwirth - 'echo $ {var}'和'echo“$ {var}”'产生相同的结果。如果启用xtrace'#!/ bin/ksh -x',甚至可以在显示之前看到'var'的值。 – 2014-08-29 14:34:48

回答

5

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

测试脚本:

#!/bin/ksh 
cat <<EOF 
    $PWD "$PWD" '$PWD' 
EOF 
echo `cat <<EOF 
    $PWD "$PWD" '$PWD' 
EOF 
` 
echo $(cat <<EOF 
    $PWD "$PWD" '$PWD' 
EOF 
) 

输出为不同的炮弹:

  • 的Linux版本KSH中号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' 
  • AIX版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" 

解决方法:

  1. 计算从这里文件

    abc=xyz 
    STR="'$abc'" 
    x=$(cat <<EOF 
        $abc "$abc" $STR 
    EOF 
    ) 
    
  2. 使用此文件中的函数,而不是直接

    fn() { 
        cat <<EOF 
        $abc "$abc" '$abc' 
    EOF 
    } 
    abc=xyz 
    x=$(fn) 
    
    外单引号字符串