如何在 bash 脚本中渲染不带引号的变量?

如何在 bash 脚本中渲染不带引号的变量?

以下脚本:

$ cat runme01.sh 
#!/bin/bash

A=myval
B=$A/{fix}
C=$A/fix

set -xT

echo $B
echo $C

如果运行则打印以下内容:

$ ./runme01.sh 
+ echo 'myval/{fix}'
myval/{fix}
+ echo myval/fix
myval/fix

如您所见,变量是用单引号B传递的,而变量是不带单引号传递的。echoC

可能是大括号造成的。

我想总是不带引号地传递它们。怎么做?

答案1

切勿尝试将跟踪输出解释为纯粹信息性的内容。这是调试输出。

事实上,它显示单引号中的大括号并没有多大意义,除了 shell 将该特定字符串解释为myval/{fix}其他任何内容之外。特别是,它确实不是意味着该字符串被引用了! shell 在跟踪输出中添加单引号,因为大括号是有时但是,在这种情况下它们不是特殊的(因为您从未使用实际的大括号扩展)。

这里发生同样的情况(在空目录中运行):

$ echo *
+ echo '*'
*

我的命令中没有引用 the *,因此 shell 会尝试来扩展它。它不会扩展到任何东西,因此它保持未扩展状态。生成跟踪输出的代码注意到*字符串中有 a 并将其引用。这是根据跟踪打印的字符串中存在的字符机械添加单引号,它不会以任何方式影响命令或其结果。

再次说明这一点:

$ ls -l
total 0
-rw-r--r--  1 kk  wheel  0 Jun 14 20:15 "filename"
-rw-r--r--  1 kk  wheel  0 Jun 14 20:13 'filename'
-rw-r--r--  1 kk  wheel  0 Jun 14 20:14 *
-rw-r--r--  1 kk  wheel  0 Jun 14 20:14 **
-rw-r--r--  1 kk  wheel  0 Jun 14 20:14 123
-rw-r--r--  1 kk  wheel  0 Jun 14 20:14 file
-rw-r--r--  1 kk  wheel  0 Jun 14 20:14 long name
-rw-r--r--  1 kk  wheel  0 Jun 14 20:14 {}
$ echo *
+ echo '"filename"' ''\''filename'\''' '*' '**' 123 file 'long name' '{}'
"filename" 'filename' * ** 123 file long name {}

即,字符串中的某些字符将导致生成跟踪输出的代码在bash. shell 还会转义字符串中的单引号。

将此与dashor进行比较pdksh

$ echo *
+ echo "filename" 'filename' * ** 123 file long name {}
"filename" 'filename' * ** 123 file long name {}

这些特定的 shell 不会添加引号(或转义单引号)。其实没关系,只是调试输出。


始终使用双引号变量扩展,除非您明确希望 shell 对字符串执行分词和文件名生成(通配)。

双引号并不总是需要的,但是记住始终使用双引号比记住不需要的上下文更容易。

您的脚本已更正:

#!/bin/bash

A=myval
B="$A/{fix}"
C="$A/fix"

set -xT

printf '%s\n' "$B"
printf '%s\n' "$C"

这将确保您始终获得这些值$B并将$C其打印到标准输出,无论其值如何。在您的原始代码中, if $Ahad was *, using$B$Cunquoted 可能会拉入一些匹配的文件名。

请注意,跟踪输出仍将使用myval/{fix}此代码引用字符串。别担心,这没有任何意义,它只是 shell 试图对其调试输出提供帮助。

有关的:

答案2

设置IFS=$'\n'后就不会发生分词,并且您可以在没有引号的情况下执行所有操作。

可能存在安全风险,但据我所知,它是针对 api 内容的,无论如何我都不会使用 bash 脚本。

有人说它对 x 或 y 不起作用,但它确实有效。

相关内容