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

不想你离开。 提交于 2019-12-13 09:51:39

问题


I've searched and found a lot of examples of if elif functions, but none I have found seem to also include logical AND or OR operators.

I'm having trouble with the following if statement in a bash script:

#!/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

I'm getting the ol' bash: [: too many arguments error for both the IF and the ELIF, and I can't seem to get it to work. Do bash scripts not like their IF statements to get this complex? Doesn't seem overly optimistic to expect this level of comparison, is it?


回答1:


You are mixing the syntax of [ aka test and Bash itself. Between [ and ], -a is a boolean AND, but it is only a feature of this particular command.

In the general case, command1 && command2 will execute command2 only if command1 returns success, and similarly, command1 || command2 will execute command2 only if command1 returns failure.

So you can say

if [ condition1 -a condition2 ]

or

if [ condition1 ] && [ condition2 ]

But anyway, your code looks like you actually want case instead. I'm having a bit of an issue following the logic of your script, but it can be simplified quite a lot, because there are actually no situations where basename $PWD can be the empty string (in the root directory, the basename is /). Also, in the elif branch, you already know that $BASE is not empty (ignoring for now the fact that it never will be empty), because if it were, the if branch would have been taken already.

Anyway, assuming you want to check whether we are in (a) the root directory or a directory exactly four levels down; or (b) in a non-root directory less than four levels down; or else (c) somewhere else (which means a directory five or more levels down), try this. Because case will take the first matching branch (keeping in mind that * will match even a string containing a slash in this context if necessary), I had to reorder these slightly.

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



回答2:


You should use || and && :

#!/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



回答3:


The problem reside in the comparison, you are using the option -a (File) that returns true if file exists, but the expression "$BASE" != "" is not a File.

You should use the logic "and" and "or" instead of (-a, -o) option.

This code works for me:

#!/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


来源:https://stackoverflow.com/questions/29643627/bash-script-with-logical-ands-and-ors-in-an-if-elif-else-statement

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!