Bash Syntax Error in conditional statement - bash

I am trying to code a script that will tell the user if a triangle is isosceles, equilateral, or scalene. The error is occuring in line 7 (The elif line)
#!/bin/bash
read -p "Enter a number: " x
read -p "Enter a number: " y
read -p "Enter a number: " z
let "a = x + y + z"
if [ $x -eq $y ] && [ $y -eq $z ]
then echo "EQUILATERAL"
elif [[[ $x -eq $y ] && [ $y != $z ]] || [[ $x -eq $z ] && [ $z != $y ]] || [[ $y -eq $z ] && [ $z != $x ]]]
then echo "ISOSCELES"
elif [ $a -gt 1000 ]
then echo "Cannot equal more than 1000"
fi
I do realize that I could do the same thing with multiple elif lines, but I also have another elif as well and I want to keep it clean. Thanks all!

It seems like you think square brackets in the shell are like parentheses in C-style programming languages. That's not how they work. [ is a synonym for the test command, the condition it introduces ends with ]. And [[ is a special token that introduces a conditional expression, which ends with ]]. You can't mix them up, you can't add additional brackets like [[[, and they don't nest.
The grouping operators in the shell are { ... } and ( ... ); the latter also creates a subshell.
elif ( [[ $x -eq $y ]] && [[ $y != $z ]] ) || ( [[ $x -eq $z ]] && [[ $z != $y ]] ) || ( [[ $y -eq $z ]] && [[ $z != $x ]] )

Related

using [[ in bash ifelse scripting gives an error [duplicate]

This question already has answers here:
Difference between sh and Bash
(11 answers)
How to use double or single brackets, parentheses, curly braces
(9 answers)
Closed 3 months ago.
I am doing a simple if else program in bash.
I am trying to understand the difference between [ and (( and [[
this below code works fine
#!/bin/bash
echo "enter a number"
read num
if [ $num -ge 1 -a $num -lt 10 ]
then
echo "A"
elif [ $num -ge 10 -a $num -lt 90 ]
then
echo "B"
elif [ $num -ge 90 -a $num -lt 100 ]
then
echo "C"
else
echo "D"
fi
This code also works fine
#!/bin/bash
echo "enter a number"
read num
if (( num >= 1)) && ((num<10))
then
echo "sam"
elif ((num >= 10)) && ((num < 90 ))
then
echo "ram"
elif ((num >= 90)) && ((num <100))
then
echo "rahim"
else
echo "tara"
fi
but when i try to use [[ there is a problem
#!/bin/bash
echo "enter a number"
read num
if [[ "num" -ge "1" ]] && [[ "num" -lt "10" ]]
then
echo "A"
elif [[ "num" -ge "10" ]] && [[ "num" -lt "90" ]]
then
echo "B"
elif [[ "num" -ge "90" ]] && [[ "num" -lt "100" ]]
then
echo "C"
else
echo "D"
fi
sourav#LAPTOP-HDM6QEG8:~$ sh ./ifelse2.sh
enter a number
50
./ifelse2.sh: 4: [[: not found
./ifelse2.sh: 7: [[: not found
./ifelse2.sh: 10: [[: not found
./ifelse2.sh: 14: echo D: not found
can someone explain this,i tried without double quoting the variable too.

Values of an array not comparing to numbers correctly

Im trying to get an array from grades.txt, and determine what letter grade it should be assigned.
I either get
hw4part2.sh: line 26: [: : integer expression expected
If i use -ge or
hw4part2.sh: line 26: [: : unary operator expected
If i use >=
Below is the code im trying to get working
mapfile -t scores < grades.txt
numOScores=0
numOA=0
numOB=0
numOC=0
numOD=0
numOF=0
DoneWScores=0
A=90
B=80
C=70
D=60
F=59
while [ $DoneWScores -eq 0 ]
do
numOScores=$((numOScores + 1))
if [ "${scores[$numOScores]}" -ge "$A" ]
then
echo "A"
elif [ "${scores[$numOScores]}" -ge "$B" ]
then
echo "B"
elif [ "${scores[$numOScores]}" -ge "$C" ]
then
echo "C"
elif [ "${scores[$numOScores]}" -ge "$D" ]
then
echo "D"
elif [ "${scores[$numOScores]}" -le "$F" ]
then
echo "F"
else
echo "Done/error"
DoneWScores=1
fi
done
If anyone knows what my problem is, that'd be greatly appreciated
Consider this:
#!/usr/bin/env bash
if (( ${BASH_VERSINFO[0]} < 4 )); then
echo "Bash version 4+ is required. This is $BASH_VERSION" >&2
exit 1
fi
letterGrade() {
if (( $1 >= 90 )); then echo A
elif (( $1 >= 80 )); then echo B
elif (( $1 >= 70 )); then echo C
elif (( $1 >= 60 )); then echo D
else echo F
fi
}
declare -A num
while read -r score; do
if [[ $score == +([[:digit:]]) ]]; then
grade=$(letterGrade "$score")
(( num[$grade]++ ))
echo "$grade"
else
printf "invalid score: %q\n" "$score"
fi
done < grades.txt
for grade in "${!num[#]}"; do
echo "$grade: ${num[$grade]}"
done | sort

Why is it saying integer expected? [duplicate]

This question already has answers here:
How do I test if a variable is a number in Bash?
(40 answers)
Closed 2 years ago.
#!/bin/bash
if [ "$1" == "" ] || [ "$2" == "" ] || [ "$3" == "" ]
then
echo This is empty or does not have all 3 parameters
exit
elif [ "$1" -lt 0 ]
then
echo This aint a number
exit
fi
Trying to run a script it is suppose first check if 3 positional parameters were entered,
secondly check if the input are numbers and then display the largest. I got the first if statement to work but when I input a string for the first parameter to test the elif statement an error that says integer expected.
you have to review the regex to check if string only contains digits, but you may try this:
#!/bin/bash
if [[ "$1" == "" ]] || [[ "$2" == "" ]] || [[ "$3" == "" ]]
then
echo "This is empty or does not have all 3 parameters"
exit
elif ! [[ "$1" =~ ^[0-9]+$ ]]
then
echo "This aint a number"
exit
fi
Note that [[ is actually a command/program that returns either 0 (true) or 1 (false). Any program that obeys the same logic (like all base utils, such as grep(1) or ping(1)) can be used as condition :
[[ -z STRING ]] #Empty string
[[ -n STRING ]] #Not empty string
[[ STRING == STRING ]] #Equal
[[ STRING != STRING ]] #Not Equal
[[ NUM -eq NUM ]] #Equal
[[ NUM -ne NUM ]] #Not equal
[[ NUM -lt NUM ]] #Less than
[[ NUM -le NUM ]] #Less than or equal
[[ NUM -gt NUM ]] #Greater than
[[ NUM -ge NUM ]] #Greater than or equal
[[ STRING =~ STRING ]] #Regexp
(( NUM < NUM )) #Numeric conditions
also to check if the string contains only digits/numerical cheracter
[[ "$1" =~ ^[0-9]+$ ]]
Please use a regex to check for number
#!/bin/bash
if [ $1 == "" ] || [ $2 == "" ] || [ $3 == "" ]
then
echo This is empty or does not have all 3 parameters
exit
elif ! [[ $1 =~ ^[0-9]+$ ]]
then
echo This aint a number
exit
fi

How to use multiple condition in if statement in bash?

Actually I am a new bash learner. I can use one condition in bash command. But how to use multiple condition in bash? I can use if statement like this:
read a
if [ $a = "y" ] ; then
echo "YES"
elif [ $a = "Y" ] ; then
echo "YES"
else
echo "NO"
fi
I am finding something like this:
read a b c
if [ $a -eq $b and $b -eq $c ] ; then
echo "EQUILATERAL"
elif [ $a -eq $b or $b -eq $c ] ; then
echo "ISOSCELES"
else
echo "SCALENE"
fi
I just want to know, what to use instead of and and or?
Use && for and (|| for or)
read a b c
if [ "$a" == "$b" ] && [ "$b" == "$c" ] ; then
echo "EQUILATERAL"
elif [ "$a" == "$b" ] || [ "$b" == "$c" ] ; then
echo "ISOSCELES"
else
echo "SCALENE"
fi
Use && and || to have multiple conditions. Additionally, change the square brackets to parentheses. Additionally change the -eq to == since you're comparing numbers and not strings. This works:
#!/bin/bash
read a b c
if (( $a == $b )) && (( $b == $c )); then
echo "EQUILATERAL"
elif (( $a == $b )) || (( $b == $c )) ; then
echo "ISOSCELES"
else
echo "SCALENE"
fi
In addition to the prior answers, the correct way to use compound expression in a single [ or test (they are the same) clause is to use -a (for and) and -o (for or).
(e.g. testing if both file1 and file2 are readable):
if [ -r "$file1" -a -r "$file2 ]
then
# do something with the files
fi
Using test itself:
if test -r "$file1" -a -r "$file2
then
# do something with the files
fi
The portable way of doing this inside test brackets is to use -a and -o. Beware however that -eq is a numeric comparison, so you need to make sure your variables are numeric before comparing them. Something like this:
#! /bin/sh
read a b c
expr "$a" : '[0-9][0-9]*$' \& "$b" : '[0-9][0-9]*$' \& "$c" : '[0-9][0-9]*$' >/dev/null || exit
if [ $a -eq $b -a $b -eq $c ] ; then
echo "EQUILATERAL"
elif [ $a -eq $b -o $b -eq $c ] ; then
echo "ISOSCELES"
else
echo "SCALENE"
fi

Bash if statement with multiple conditions throws an error

I'm trying to write a script that will check two error flags, and in case one flag (or both) are changed it'll echo-- error happened. My script:
my_error_flag=0
my_error_flag_o=0
do something.....
if [[ "$my_error_flag"=="1" || "$my_error_flag_o"=="2" ] || [ "$my_error_flag"="1" && "$my_error_flag_o"="2" ]]; then
echo "$my_error_flag"
else
echo "no flag"
fi
Basically, it should be, something along:
if ((a=1 or b=2) or (a=1 and b=2))
then
display error
else
no error
fi
The error I get is:
line 26: conditional binary operator expected
line 26: syntax error near `]'
line 26: `if [[ "$my_error_flag"=="1" || "$my_error_flag_o"=="2" ] || [ "$my_error_flag"="1" && "$my_error_flag_o"="2" ]]; then'
Are my brackets messed up?
Use -a (for and) and -o (for or) operations.
tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html
Update
Actually you could still use && and || with the -eq operation. So your script would be like this:
my_error_flag=1
my_error_flag_o=1
if [ $my_error_flag -eq 1 ] || [ $my_error_flag_o -eq 2 ] || ([ $my_error_flag -eq 1 ] && [ $my_error_flag_o -eq 2 ]); then
echo "$my_error_flag"
else
echo "no flag"
fi
Although in your case you can discard the last two expressions and just stick with one or operation like this:
my_error_flag=1
my_error_flag_o=1
if [ $my_error_flag -eq 1 ] || [ $my_error_flag_o -eq 2 ]; then
echo "$my_error_flag"
else
echo "no flag"
fi
You can use either [[ or (( keyword. When you use [[ keyword, you have to use string operators such as -eq, -lt. I think, (( is most preferred for arithmetic, because you can directly use operators such as ==, < and >.
Using [[ operator
a=$1
b=$2
if [[ a -eq 1 || b -eq 2 ]] || [[ a -eq 3 && b -eq 4 ]]
then
echo "Error"
else
echo "No Error"
fi
Using (( operator
a=$1
b=$2
if (( a == 1 || b == 2 )) || (( a == 3 && b == 4 ))
then
echo "Error"
else
echo "No Error"
fi
Do not use -a or -o operators Since it is not Portable.
Please try following
if ([ $dateR -ge 234 ] && [ $dateR -lt 238 ]) || ([ $dateR -ge 834 ] && [ $dateR -lt 838 ]) || ([ $dateR -ge 1434 ] && [ $dateR -lt 1438 ]) || ([ $dateR -ge 2034 ] && [ $dateR -lt 2038 ]) ;
then
echo "WORKING"
else
echo "Out of range!"
You can get some inspiration by reading an entrypoint.sh script written by the contributors from MySQL that checks whether the specified variables were set.
As the script shows, you can pipe them with -a, e.g.:
if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
...
fi

Resources