【问题标题】:Bash Can not get IF to work like I want toBash 无法让 IF 像我想要的那样工作
【发布时间】:2023-03-06 06:10:01
【问题描述】:

我需要理解 bash if 表达式。当然,我用过谷歌。我知道它是这样的:

if [ expr operator expr ]
then
doSomeThing
fi

但是,我知道 Bash 没有布尔数据类型。我想检查作为参数 ($1) 传递的文件是否存在。我会直接做这件事的方式:

if [ -e $1 = true ] 
then 
echo "File exists."
fḯ

或者可能是这样的:

if [ -e $1 ] #Assuming that this is true only if file in $1 exists. 

这些都不起作用,我不确定 [ ] 是什么意思。 -e $1 似乎是一个明智的选择,但它总是正确的吗?字符串和整数有不同的运算符。而且我不能使用括号将表达式组合在一起。这太令人困惑了。

有人有一些提示吗?如果我尝试过任何其他语言,bash 中的 IF 就无法正常工作。

【问题讨论】:

    标签: bash types boolean


    【解决方案1】:

    [...]

    表示程序/usr/bin/test... 作为参数执行并检查其返回值(0 表示truex != 0 表示false(是的,0 真正表示@此处为 987654328@,因为 0 是 UNIX 中的 OK 退出代码))。所以

    if [ -e $1 ]; then
        echo "ok"
    fi
    

    是正确的。是一样的

    if test -e $1; then
        echo "ok"
    fi
    

    唯一的问题是$1 可能包含空格。如果是这样,/usr/bin/test 会感到困惑,因为它有 3 个或更多参数。第一个 (-e) 是一元运算符(需要一个参数)。既然你给了它 2 个或更多(一个 /usr/bin/test 参数是 -e 本身),它会这样抱怨:

    ...: binary operator expected
    

    所以,只需使用

    if [ -e "$1" ];then
        echo "ok"
    fi
    

    如果$1 包含空格,这甚至可以工作。另一种可能性是使用

    if [[ -e $1 ]]; then
        echo "ok"
    fi
    

    这将做同样的事情,但它会由 bash 本身进行评估,并且不会分叉 /usr/bin/test 程序。

    化合物与往常一样,但-a 表示and-o 表示or。所以

    if [ -e /etc/fstab -a -e "$1" ]; then
       echo "ok"
    fi
    

    如果/etc/fstab 和作为第一个命令行参数给出的文件存在,则会回显。

    【讨论】:

    • 在 $1 => "$1" 周围添加 "" 时会发生什么?
    • 无论有多少空格,它都会为 /usr/bin/test 提供一个参数。
    • 除了 [test 也是 Bash 内置函数,因此执行的优先级高于 /usr/bin/{[,test}
    【解决方案2】:

    正如其他人所提到的,[ 实际上是 test 命令,因此它的参数会根据标准参数解析规则进行解析,这会导致一些相当不方便和令人困惑的语法。例如,您可以在测试命令中使用括号、<>,但最好将它们转义,否则 shell 会将它们视为不幸的事情。

    有一个更好的解决方案:conditional expression,它看起来很像老式的测试命令,但在表达式周围使用[[ ]] 而不是[ ]。因为它不被解析为命令,所以它的语法更加自然,并且还具有一些更强大的功能:

    if [[ -e $1 && ! -d $1 ]]; then  # if $1 exists but isn't a directory...
        # note that quotes are not needed, since $1 will not undergo word splitting
    [[ $string == done ]] # string comparison
    [[ $string == a* ]] # glob-style pattern matching: does $string start with "a"?
    [[ $string == "*"* ]] # partial glob: does $string start with "*"?
    [[ $string =~ ^[[:upper:]] ]] # regex matching: does $string start with an upper-case letter?
    [[ $string < g ]] # string comparison: is $string alphabetically before "g"
    [[ $num -lt 5 ]] # numeric comparison: is $num numerically less than 5
    

    【讨论】:

      【解决方案3】:
      1. man test
      2. 这应该可行:

        function foo() {
          if [ -e "$1" ] ; then
            echo "$1 exists"
          fi
        }
        
      3. 复合表达式有几种写法: 和:

        [ expr1 -a expr2 ]
        

        或:

        [ expr1 -o expr2 ]
        

        您也可以使用[[ expr &amp;&amp; expr || expr ]] 语法

      【讨论】:

        【解决方案4】:

        [ ] 是 bash 测试命令的简写 http://ss64.com/bash/test.html

        if bash 中的操作检查用于测试的命令的返回码是否为 0。

        您可以使用以下命令检查任何命令的返回状态: echo $?

        例如试试这个:

        测试 -e myfile.txt 回声$? [-e myfile.txt] 回声?$

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-06-12
          • 1970-01-01
          • 2019-04-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多