以下脚本:
$ 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
传递的,而变量是不带单引号传递的。echo
C
可能是大括号造成的。
我想总是不带引号地传递它们。怎么做?
答案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 还会转义字符串中的单引号。
将此与dash
or进行比较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 $A
had was *
, using$B
和$C
unquoted 可能会拉入一些匹配的文件名。
请注意,跟踪输出仍将使用myval/{fix}
此代码引用字符串。别担心,这没有任何意义,它只是 shell 试图对其调试输出提供帮助。
有关的:
答案2
设置IFS=$'\n'
后就不会发生分词,并且您可以在没有引号的情况下执行所有操作。
可能存在安全风险,但据我所知,它是针对 api 内容的,无论如何我都不会使用 bash 脚本。
有人说它对 x 或 y 不起作用,但它确实有效。