问题
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