【问题标题】:A case in which both test -n and test -z are truetest -n 和 test -z 都为真的情况
【发布时间】:2012-02-28 16:25:52
【问题描述】:
#! /bin/bash

echo "Please input 2 nums: "

read a b

if [ -z $b ]; then
        echo b is zero !
fi

if [ -n $b ]; then
        echo b is non-zero !
fi

运行脚本时,只输入1个数字,其他留空,则b应为空。但结果是两个 echo 都被打印出来了。

-laptop:~$ ./test.sh 
Pleaes input 2 nums: 
5 
b is zero !
b is non-zero !

b 既为空又非空?!有人可以对此发表评论吗?谢谢!

~

【问题讨论】:

  • +1 用于显示您的代码和实际输出。祝你好运!
  • 如果您只为 Bash 编写代码,那么您可能希望将 [ 条件句替换为 [[。推荐阅读:mywiki.wooledge.org/BashFAQ/031
  • 这里有竞争条件。在两个if 测试之间,磁盘上的文件大小可能会发生变化。如果你的代码实际上有这种形式,你应该使用else

标签: linux shell


【解决方案1】:

替换

if [ -z $b ]; then

if [ -z "$b" ]; then

在另一个 if 条件下也这样做。

查看http://tldp.org/LDP/abs/html/testconstructs.html 了解一些有趣的测试。

【讨论】:

  • 是的,它有效!谢谢。但我想知道为什么“”会产生如此大的差异?
  • 没有引号,未初始化的变量评估为 nothing,因此 shell 评估 if [ -z ],这是正确的,因为“-z”被解析为(非空) 字符串,计算结果为true
  • 底线:总是在不干扰其他期望结果的地方引用你的东西(例如扩展到多个参数)。
  • @AdamLiss 是对的:shell 首先计算[ ... ] 中的参数数量。如果它只是一个参数,则如果参数不为空,则结果为真。 As the man page says "test[ 内置函数使用一组基于参数数量的规则来评估条件表达式。"
【解决方案2】:

这一切都在引号中。我不记得在哪里,但是最近有人在 SO 或 USE 上解释了这一点 - 如果没有引号,它实际上不会进行空/非空字符串测试,而只是检查 -n-z非空字符串本身。正是同一个测试使这成为可能:

$ var=-n
$ if [ "$var" ]
then
    echo whut
fi

返回whut

这意味着你也可以有一种函数式编程:

$ custom_test() {
    if [ "$1" "$2" ]
    then
        echo true
    else
        echo false
    fi
}

$ custom_test -z "$USER"
false
$ custom_test -n "$USER"
true

【讨论】:

    【解决方案3】:

    -n 测试要求在测试括号内引用字符串。在! -z 中使用不带引号的字符串,或者甚至只是在测试括号内单独使用不带引号的字符串通常都可以,但是,这是一种不安全的做法。始终引用经过测试的字符串。

    $ b=''
    $ [ -z $b ] && echo YES  # after expansion: `[ -z ] && echo YES` <==> `test -z && echo YES`
    YES
    $ [ -n $b ] && echo YES  # after expansion: `[ -n ] && echo YES` <==> `test -n && echo YES`
    YES
    

    test 反对什么,屈服于true

    【讨论】:

    • 感谢您的回答。但是正如您所提到的,测试中未引用的字符串通常可以工作,但是为什么这种情况会失败?能给点提示吗?
    猜你喜欢
    • 1970-01-01
    • 2018-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-11
    • 2011-01-01
    相关资源
    最近更新 更多