如何在单引号内使用变量

Moh*_*HME 12 shell quoting variable

我有一个应用程序,它以嵌入在单引号中的双引号作为输入属性。以这个正确的命令为例:

command -p 'cluster="cl1"'
Run Code Online (Sandbox Code Playgroud)

为了使其自动化,我创建了一个$CLUSTER用作变量的 bash 文件。我的命令应该如何?换句话说,我应该放什么来代替 cl1?

请注意,如果我修改了上面的命令,它将不被接受。例如:command -p "cluster=cl1"不被接受

mik*_*erv 9

看起来您的命令可能正在根据命令行上给出的参数设置环境变量。也许你可以这样做:

CLUSTER=cl1; cluster=$CLUSTER command
Run Code Online (Sandbox Code Playgroud)

...并在调用时为其设置环境。

否则,shell 引号通常会分隔参数或从 shell 解释中转义其他特殊的 shell 字符。您可以根据各种规则在其他类型中包含(并因此转义)不同类型的 shell 引号:

  • "''''" - 软引用字符串可以包含任意数量的硬引用。
  • "\""-\反斜杠可以转义软引用字符串中""软引用。
    • 在这种情况下,\\反斜杠也会转义自身、\$扩展标记和\newlines,如下所述,但按字面意思处理。
  • "${expand} and then some"- 软引号字符串可以包含解释的 shell$扩展。
  • '"\'-'硬引用字符串可以包含硬引用以外的任何字符'
  • \- 不带引号的反斜杠将转义任何后续字符以进行字面解释 - 甚至是另一个反斜杠 - 除了\newline。
    • \\newline 情况下,\反斜杠和\newline 都从生成的解释命令中完全删除。
  • ${parameter+expand "$parameter"}- 除了少数特殊情况外,shell 扩展产生的引号几乎从不用作分隔符。我不会冒险在这里进一步描述这些。

我认为任何应用程序都会在其命令行参数中解释引号很奇怪。这种做法没有多大意义——至少对于 shell 来说——引用的主要目的通常是界定一个论点。然而,在调用时,参数总是已经\0NUL字符分隔,因此引用不能起到太大作用。

甚至 shell 通常只会在使用-cswitch调用时解释其调用参数中的引号- 这表示它的第一个操作数实际上是它应该在调用时运行的 shell 脚本。这是两次评估输入的情况。

尽管如此,您可以做很多事情来通过命令行上的参数传递文字引号。例如:

CLUSTER='"cl1"'; command -p "cluster=$CLUSTER"
Run Code Online (Sandbox Code Playgroud)

正如我之前在评论中指出的那样,您可以"在本身"被引用的扩展中包含引号。

CLUSTER=cl1; command -p "cluster=\"$CLUSTER\""
Run Code Online (Sandbox Code Playgroud)

您可以在"带引号的字符串中使用\反斜杠转义"

CLUSTER=cl1; command -p cluster='"'"$CLUSTER"'"'
Run Code Online (Sandbox Code Playgroud)

您可以交替和连接引用样式以达到您想要的最终结果,如上面@jimmij所述

CLUSTER=cl1; ( set -f; IFS=; command -p cluster=\"$CLUSTER\" )
Run Code Online (Sandbox Code Playgroud)

您可以禁用文件名生成$IFS拆分 - 从而$expansion根本不需要引用- 所以只引用引号。这恐怕是矫枉过正了。

最后,可能会使用另一种类型的 shell 引用。正如我之前提到的sh -c "$scriptlet",shell 调用的形式通常用于在命令行上提供 shell 脚本。当$scriptlet变得复杂时 - 例如当引号必须包含其他引号时 - 使用 here-document 通常是有利的,sh -s而不是 - 特别指示 shell 将所有后续操作数分配给位置参数,就像在这种-c情况下所做的那样并且还没有从stdin.

如果您的命令必须以这种方式解释引号,那么如果它可以在文件输入中这样做,我会认为它会更好。例如:

CLUSTER=cl1
command --stdin <<-SCRIPT
    cluster="$CLUSTER"
SCRIPT
Run Code Online (Sandbox Code Playgroud)

如果不引用的分隔符<<here-document的所有内容被视为几乎完全一样,他们是那么"的软引用-除了"双引号本身不会特殊对待。因此,如果我们cat改为运行上面的代码:

CLUSTER=cl1
cat <<-SCRIPT
        cluster="$CLUSTER"
SCRIPT
Run Code Online (Sandbox Code Playgroud)

...它打印...

cluster="cl1"
Run Code Online (Sandbox Code Playgroud)