【问题标题】:ksh88 changing single quotes to double quotes inside heredocs?ksh88将heredocs中的单引号更改为双引号?
【发布时间】:2014-10-23 13:24:39
【问题描述】:

我似乎遇到了一个特定于 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 来观察。

在不使用反引号的情况下,如何防止上述代码 sn-p 中的 '" 转换?


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

【问题讨论】:

  • 所描述的行为听起来像一个错误。将反引号更改为 $(…) 不应更改输出内容。不能升级到ksh93吗?
  • @JonathanLeffler - 如果它是一个错误,那么它看起来很刻意。至于切换到ksh93,这不一定是一种选择。实际的脚本需要在多个不同版本的 AIX 和 Solaris 服务器上运行。少数有 ksh93,但大多数只有 ksh88。
  • @AdrianFrühwirth - echo ${var}echo "${var}" 在上述所有情况下产生相同的结果。如果启用 xtrace #!/bin/ksh -x,您甚至可以在 var 显示之前看到它的值。
  • +1 用于模型问题。要是!您似乎知道您的 kshs,但我对 Solaris 和 AIX 的经验是,您可能必须使用备用路径甚至备用名称,例如 dtksh 才能访问 ksh93。 (不记得我在 AIX 上有什么,但它在那里)。祝你好运。
  • 其他人也看到了这个。来自in-ulm.de/~mascheck/various/cmd-subst:“在ksh88 中,至少从a 版到i 版,您必须注意$() 中的一个微妙的引用问题。嵌入的here 文档中的单引号被转换为双引号。”。

标签: shell ksh aix


【解决方案1】:

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

测试脚本:

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

不同shell的输出:

  • 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'
  • 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. 在函数中使用here-file而不是直接

    fn() {
      cat <<EOF
        $abc "$abc" '$abc'
    EOF
    }
    abc=xyz
    x=$(fn)
    

【讨论】:

    猜你喜欢
    • 2013-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-17
    • 2021-09-03
    • 2019-10-04
    • 1970-01-01
    相关资源
    最近更新 更多