Linux 在布尔条件下,何时应将变量置于引号中?

Linux 在布尔条件下,何时应将变量置于引号中?,linux,bash,Linux,Bash,以下两个布尔表达式是否相同 if [ -n $1 ] ; then if [ -n "$1" ] ; then 这两个呢 if [ $? == 0 ] ; then if [ "$?" == 0 ] ; then 如果没有-什么时候应该将变量放在引号中?如果值可能包含空格,或者通常不是连续的字符串,请将变量放在引号中。所以 由于$?应该总是介于0和255之间,所以不需要引用它,因为它是在每个子进程返回后设置的返回值。通过直接分配字符串值(即 $?=Is of course wrong

以下两个布尔表达式是否相同

if [ -n $1 ] ; then   
if [ -n "$1" ] ; then
这两个呢

if [ $? == 0 ] ; then
if [ "$?" == 0 ] ; then

如果没有-什么时候应该将变量放在引号中?

如果值可能包含空格,或者通常不是连续的字符串,请将变量放在引号中。所以

由于
$?
应该总是介于0和255之间,所以不需要引用它,因为它是在每个子进程返回后设置的返回值。通过直接分配字符串值(即

$?=Is of course wrong and should be

 ?=Bad value assigment
因为用户变量名必须以[a-Za-z_]开头,所以不要这样做;-)

而对于$1,如果传入一个值

myscript "arg1 with spaces"
测试

if [ -n $1 ] ; then
if [ -n "$1" ] ; then  
会爆炸,

但是测试

if [ -n "$1" ] ; then  
我们会成功的


它们并不总是一样的。如果所讨论的变量为空或包含空格,则
[
命令(test的别名)的参数可能太少或太多


bash
中,可以使用内置的
[[[-n$1]]
条件构造,该构造在计算条件之前不会将变量拆分为单词,这意味着不需要双引号。

使用
[
命令(是的,这是一个命令),你几乎应该总是使用引号。例外情况非常罕见,我甚至可能不去研究它们。例如

set -- 'x -a -z b'
if [ -n $1 ]; then echo foo; fi
# … crickets
if [ -n "$1" ]; then echo foo; fi
foo
Bash还有
[[
关键字(是的,它是一个关键字),它足够聪明,可以了解扩展并避免不引用的陷阱(但在
[[
表达式中引用通常还是安全的)

由于
[
命令与POSIX兼容,并且
[[
是一种bashism,因此您可以决定何时使用它

至于第二个例子,如果您将某物与数字进行比较,则使用
=
是一种bash主义

if (( $? == 0 )); then …
但如果您正在尝试POSIX合规性,请编写它

if [ "$?" = 0 ]; then …
通常,与
$?
的直接比较是一个危险信号,因为比较命令的成功/失败正是
如果
所做的:

if somecommand; then …

somecommand
if (( $? == 0 )); then …
但是如果您确实需要使用它,
$?
是一个例外,因为它保证只会是一个单字节无符号整数,所以使用unquoted是非常安全的,尽管使用引号不会有什么坏处

$ false; if [ $? = 0 ]; then echo t; else echo f; fi
f
$ true; if [ $? = 0 ]; then echo t; else echo f; fi
t
$ false; if [ "$?" = 0 ]; then echo t; else echo f; fi
f
$ true; if [ "$?" = 0 ]; then echo t; else echo f; fi
t
$ false; if [ $? == 0 ]; then echo t; else echo f; fi
f
$ true; if [ $? == 0 ]; then echo t; else echo f; fi
t
$ false; if [ "$?" == 0 ]; then echo t; else echo f; fi
f
$ true; if [ "$?" == 0 ]; then echo t; else echo f; fi
t

感谢choroba,我试图删除我在askubuntu上提出的问题,你回答了这个问题。严格说来,“在评估条件之前不展开变量”不是真的——“不在“[]”和“]]之间的字上执行分词和文件名展开”“;执行波浪式展开、参数和变量展开、算术展开、命令替换、进程替换和引号删除。”--这里的关键是缺少分词。谢谢-我想我现在理解得更好了。是否有理由为<代码>“$”加引号?”导致布尔值以一种非预期的方式计算?就像我理解为什么将
“$1”
放在引号中会很有用,但当我将
“$?”
放在引号中时,它不起作用。请参阅编辑。下面所有优点都是+1!我不确定“$?”不起作用的意思。请尝试
设置-vx;如果[$?=0];然后echo通过;else echo失败;fi;false;f[$?=0];然后echo通过;else echo失败;fi;设置+vx
以查看发生了什么。Sub在
[…]
内的各种组合中,作为一个变体
[[…]
。祝大家好运。@SHEET:记住
[$?=0]
是一种文本比较。算术比较应该是
($?==0))
(cold也应该是
[$?-eq 0]
,但这很可怕)实际上当我引用
“$?”
布尔表达式的计算结果不同于我不引用它时的计算结果…@user784637我不知道如何解释它。这似乎不可能,除非您的系统出现严重问题或您误解了结果。我在回答中发布了一个演示。@user784637好吧,
$?
不是参数的数量,而是这是最近运行的命令的成功/失败。您可能指的是
$#
。比第一个示例更糟糕的是,请尝试:
emptyvar=“”;如果[-n$emptyvar];则回显“显然它不是空的”;fi