为什么 bash -n 和 -z 测试运算符不为 $@ 取反

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15206840/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 04:44:33  来源:igfitidea点击:

Why are the bash -n and -z test operators not inverses for $@

bashoperators

提问by Mike Samuel

function wtf() {
  echo "$*='$*'"
  echo "$@='$@'"
  echo "$@='"$@"'"
  echo "$@='""$@""'"
  if [ -n "$*" ]; then echo " [ -n $* ]"; else echo "![ -n $* ]"; fi
  if [ -z "$*" ]; then echo " [ -z $* ]"; else echo "![ -z $* ]"; fi
  if [ -n "$@" ]; then echo " [ -n $@ ]"; else echo "![ -n $@ ]"; fi
  if [ -z "$@" ]; then echo " [ -z $@ ]"; else echo "![ -z $@ ]"; fi
}

wtf

produces

产生

$*=''
$@=''
$@=''
$@=''
![ -n $* ]
 [ -z $* ]
 [ -n $@ ]
 [ -z $@ ]
$*=''
$@=''
$@=''
$@=''
![ -n $* ]
 [ -z $* ]
 [ -n $@ ]
 [ -z $@ ]

though it seems to me that [-n $@]should be false because 7.3 Other Comparison Operatorsindicates that [ -n "$X" ]should be the inverse of [ -z "$X" ]for all $X.

尽管在我看来这[-n $@]应该是错误的,因为7.3 Other Comparison Operators表明[ -n "$X" ]应该是[ -z "$X" ]for all的倒数$X

-z

string is null, that is, has zero length

String=''   # Zero-length ("null") string variable.

if [ -z "$String" ]
then
  echo "$String is null."
else
  echo "$String is NOT null."
fi     # $String is null.

-n

string is not null.

The -ntest requires that the string be quoted within the test brackets. Using an unquoted string with ! -z, or even just the unquoted string alone within test brackets (see Example 7-6) normally works, however, this is an unsafe practice. Always quote a tested string. [1]

-z

字符串为空,即长度为零

String=''   # Zero-length ("null") string variable.

if [ -z "$String" ]
then
  echo "$String is null."
else
  echo "$String is NOT null."
fi     # $String is null.

-n

字符串不为空。

-n测试要求的字符串测试括号内引用。使用带有 的不带引号的字符串! -z,或者甚至只是在测试括号中单独使用不带引号的字符串(参见示例 7-6)通常是有效的,但是,这是一种不安全的做法。始终引用经过测试的字符串。[1]

I know $@is special but I did not know it was special enough to violate boolean negation. What is happening here?

我知道它$@很特别,但我不知道它特别到足以违反布尔否定。这里发生了什么?



$ bash -version | head -1
GNU bash, version 4.2.42(2)-release (i386-apple-darwin12.2.0)


The actual numeric exit codes are all 1or 0as per

实际的数字退出代码全部10按照

$ [ -n "$@" ]; echo "$?"
0

回答by chepner

When $@is empty, "$@"doesn't expand to an empty string; it is removed altogether. So your test is not

如果$@是空的,"$@"没有扩展到空字符串; 它被完全删除。所以你的测试不是

[ -n "" ]

but rather

反而

[ -n ]

Now -nisn't an operator, but just a non-empty string, which always tests as true.

Now-n不是运算符,而只是一个非空字符串,它总是测试为真。

回答by Aaron Digulla

"$@"doesn't do what you expect. It's not a different form of "$*", it expands to the quoted list of arguments passed to the current script.

"$@"不会做你期望的。它不是 的不同形式"$*",它扩展为传递给当前脚本的带引号的参数列表。

If there are no arguments, it expands to nothing. If there are two arguments aand b c, then it expands to "a" "b c"(i.e. it preserves whitespace in arguments) while "$*"expands to "a b c"and $*would expand to a b c(three words).

如果没有参数,它会扩展为空。如果有两个参数aand b c,那么它扩展到"a" "b c"(即它保留参数中的空格)同时"$*"扩展到"a b c"并且$*将扩展到a b c(三个单词)。