Bash 在 if elif else 语句中使用逻辑与和或的脚本

Bash script with logical ands, and ors in an if elif else statement

我搜索并找到了很多 if elif 函数的示例,但是 none 我发现似乎还包括逻辑 AND 或 OR 运算符。

我在 bash 脚本中使用以下 if 语句时遇到问题:

#!/bin/bash

BASE="$(basename "${PWD}")"
REPO="$(cut -d/ -f4 <<<"${PWD}")"
if [ "$BASE" = "$REPO" ] -o [ "$BASE" = "" ]
then
  echo "[$REPO]"
elif [ "$REPO" = "" ] -a [ "$BASE" != "" ]
then
  echo "$BASE"
else
  echo "[$REPO] $BASE"
fi

我收到 IF 和 ELIF 的 ol' bash: [: too many arguments 错误,我似乎无法让它工作。 bash 脚本不喜欢他们的 IF 语句变得如此复杂吗?期待这种水平的比较似乎并不过分乐观,是吗?

你应该使用 ||&& :

#!/bin/bash

BASE="$(basename "${PWD}")"
REPO="$(cut -d/ -f4 <<<"${PWD}")"
if [ "$BASE" = "$REPO" ] || [ "$BASE" = "" ]
then
  echo "[$REPO]"
elif [ "$REPO" = "" ] && [ "$BASE" != "" ]
then
  echo "$BASE"
else
  echo "[$REPO] $BASE"
fi

问题出在比较中,您正在使用选项 -a(文件),如果文件存在,returns 为真,但表达式 "$BASE" != "" 不是文件。

您应该使用逻辑 "and" 和 "or" 而不是 (-a, -o) 选项。

这段代码对我有用:

#!/bin/bash

BASE="$(basename "${PWD}")"
REPO="$(cut -d/ -f4 <<<"${PWD}")"
if [ "$BASE" = "$REPO" ] || [ "$BASE"  = "" ]
then
  echo "[$REPO]"
elif [ "$REPO" = "" ] && [ "$BASE" != "" ]
then
  echo "$BASE"
else
  echo "[$REPO] $BASE"
fi

您正在混合 [ 又名 test 和 Bash 本身的语法。在 [] 之间,-a 是一个布尔 AND,但它只是这个特定命令的一个特性。

一般情况下,command1 && command2只有command1 returns成功才会执行command2,同理,command1 || command2会执行command2 仅当 command1 returns 失败时。

所以你可以说

if [ condition1 -a condition2 ]

if [ condition1 ] && [ condition2 ]

但无论如何,您的代码看起来确实需要 case。我在你的脚本逻辑上遇到了一些问题,但它可以简化很多,因为实际上没有 basename $PWD 可以是空字符串的情况(在根目录中,basename是 /)。此外,在 elif 分支中,您已经知道 $BASE 不为空(暂时忽略它永远不会为空的事实),因为如果它是, if 分支将已经有人拍了

无论如何,假设您想检查我们是在 (a) 根目录还是恰好四层以下的目录;或 (b) 在低于四级的非根目录中;或者 (c) 其他地方(这意味着目录下五层或更多层),试试这个。因为 case 将采用第一个匹配的分支(请记住,如果需要,* 甚至会匹配在此上下文中包含斜线的字符串),我不得不稍微重新排序。

case $PWD in
    /*/*/*/*/* )   # more than 4  (c)
        echo "[$REPO] $BASE" ;;
    / | /*/*/*/* )  # root or exactly 4  (a)
        echo "[$REPO"] ;;
    *)             # else, less than 4, not root  (b)
        echo "$BASE" ;;
esac