什么时候应该在布尔条件中用引号推送变量?

use*_*637 4 linux bash

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

if [ -n $1 ] ; then   
if [ -n "$1" ] ; then
Run Code Online (Sandbox Code Playgroud)

而这两个

if [ $? == 0 ] ; then
if [ "$?" == 0 ] ; then
Run Code Online (Sandbox Code Playgroud)

如果不是 - 什么时候应该在引号中加上变量?

she*_*ter 8

当有可能包含空格时,将变量放在引号中,或者通常不是连续的字符串.所以

因为它$?总是介于0到255之间,所以你不需要引用它,因为它是每个子进程返回后设置的返回值.不可能通过直接分配字符串值来破坏它,即

$?=Is of course wrong and should be

 ?=Bad value assigment
Run Code Online (Sandbox Code Playgroud)

因为用户变量名必须以[A-Za-z_]开头,所以不要这样做;-)

而对于1美元,如果传递的值是这样的

myscript "arg1 with spaces"
Run Code Online (Sandbox Code Playgroud)

考试

if [ -n $1 ] ; then
Run Code Online (Sandbox Code Playgroud)

会爆炸,

但是测试

if [ -n "$1" ] ; then  
Run Code Online (Sandbox Code Playgroud)

将会成功.

IHTH


koj*_*iro 8

使用[命令(是的,这是一个命令),你应该几乎总是使用引号.例外是如此罕见,我甚至可能没有进入他们.例如,

set -- 'x -a -z b'
if [ -n $1 ]; then echo foo; fi
# … crickets
if [ -n "$1" ]; then echo foo; fi
foo
Run Code Online (Sandbox Code Playgroud)

Bash还有[[关键字(是的,它是一个关键字),它足够聪明,可以了解扩展并避免不引用的陷阱.(但在[[表达式中引用它通常仍然是安全的.)

由于该[命令符合POSIX并且[[是一种基础,因此您决定何时使用哪个.

至于你的第二个例子,如果你将某些东西与数字进行比较,那么使用==就是一种基础.如果您正在为bash编写,请使用算术表达式,例如

if (( $? == 0 )); then …
Run Code Online (Sandbox Code Playgroud)

但是,如果您正在尝试POSIX合规性,请写下来

if [ "$?" = 0 ]; then …
Run Code Online (Sandbox Code Playgroud)

通常,直接比较$?是一个红旗,因为比较命令的成功/失败恰恰是if这样的:

if somecommand; then …
Run Code Online (Sandbox Code Playgroud)

比...更好

somecommand
if (( $? == 0 )); then …
Run Code Online (Sandbox Code Playgroud)

但是如果你确实需要使用它,那$?就是一个例外,因为它保证只能是一个单字节的无符号整数,因此使用不带引号是非常安全的,尽管它引用并没有什么坏处.

$ 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
Run Code Online (Sandbox Code Playgroud)