如何在单引号内使用变量


11

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

command -p 'cluster="cl1"'

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

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


2
CLUSTER='"cl1"'; command -p "cluster=$CLUSTER"
mikeserv'1

另一种可能性(如果您更喜欢cliCLUSTER变量中不带引号的情况下存储):CLUSTER='cl1'; command -p 'cluster="'"$CLUSTER"'"'
jimmij 2015年

最后,我找到了正确的答案。谢谢@jimmij。
Mohamad-Jaafar NEHME 2015年

Answers:


8

看来您的命令可能是根据命令行中给定的参数设置环境变量的。可能您可以这样做:

CLUSTER=cl1; cluster=$CLUSTER command

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

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

  • "''''" -用软引号括起来的字符串可以包含任意数量的硬引号。
  • "\""- \反斜杠可以""软引用字符串中转义软引用。
    • 在这种情况下,\\反斜杠也将自身,\$扩展令牌和\n后缀转义,如下所述,但是在其他方面会按字面意义对待。
  • "${expand} and then some"-用软引号括起来的字符串可以包含解释的外壳$扩展。
  • '"\'- '硬引号字符串可以包含除'硬引号以外的任何字符。
  • \-不带引号的反斜杠将转义任何后续字符以进行字面解释-甚至还有另一个反斜杠-斜线除外\n
    • \\newline的情况下,\反斜杠和\newline都将从生成的解释命令中完全删除。
  • ${parameter+expand "$parameter"}-除少数特殊情况外,由Shell扩展产生的引号几乎永远不会用作分隔符。我不会在这里进一步描述这些。

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

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

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

CLUSTER='"cl1"'; command -p "cluster=$CLUSTER"

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

CLUSTER=cl1; command -p "cluster=\"$CLUSTER\""

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

CLUSTER=cl1; command -p cluster='"'"$CLUSTER"'"'

您可以如上@jimmij 所述替换和连接引用样式以达到所需的最终结果。

CLUSTER=cl1; ( set -f; IFS=; command -p cluster=\"$CLUSTER\" )

您可以同时禁用文件名的生成$IFS拆分-从而完全避免了用引号引起$expansion来-因此仅用引号引起来。这可能是矫kill过正。

最后,还有另一种可以使用的外壳引号。如前所述sh -c "$scriptlet",shell调用的形式通常用于在命令行上提供shell的脚本。但是,当$scriptlet变得复杂时(例如,当引号必须包含其他引号时),使用here-document通常会更有利,sh -s而相反,在这种情况下,shell被专门指示将所有后续操作数分配给位置参数,就像在-c情况下那样而且还需要从中提取其脚本stdin

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

CLUSTER=cl1
command --stdin <<-SCRIPT
    cluster="$CLUSTER"
SCRIPT

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

CLUSTER=cl1
cat <<-SCRIPT
        cluster="$CLUSTER"
SCRIPT

...打印...

cluster="cl1"

1

就像mikeserv写道:

 CLUSTER='"cl1"'; command -p "cluster=$CLUSTER" 

“双引号”包含空格/元字符,每字面每一个扩展:"$var""$(command "$var")""${array[@]}""a & b"。使用'single quotes'代码或文字$'s: 'Costs $5 US'ssh host 'echo "$HOSTNAME"'。参见
http://mywiki.wooledge.org/
行情http://mywiki.wooledge.org/Arguments
http://wiki.bash-hackers.org/syntax/words


你说得对,谢谢。但是,自动化呢?假设我想阅读CLUSTER?我将再次遇到相同的问题:单引号内的变量
Mohamad-Jaafar NEHME 2015年

@Moi-自动化没什么大不了的,尽管您必须清理"字符变量-仅第一个和最后一个就足够了。真正的问题是您的应用在arg中解释引号。解释参数中的引号几乎绝不是一个好主意,因为引号应仅是分隔参数的一种手段-并且在调用时,分隔\0NUL在每种情况下均由s 处理。也许有更好的方法将您想要的信息传递给应用程序?喜欢一个command --'script=/path/to/some/file'还是什么?
mikeserv'1
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.