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
Related
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
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 ]] )
Suppose I am writing the following in a bash script:
if [ -z $a ] || [ -z $b ] ; then
usage
fi
It works but I would like to write it with short-circuiting as follows:
[ -z $a ] || [ -z $b ] || usage
Unfortunately it does not work. What am I missing ?
You want to execute usage in case either 1st or 2nd condition are accomplished. For that, you can do:
[ -z $a ] || [ -z $b ] && usage
Test:
$ [ -z "$a" ] || [ -z "$b" ] && echo "yes"
yes
$ b="a"
$ [ -z "$a" ] || [ -z "$b" ] && echo "yes"
yes
$ a="a"
$ [ -z "$a" ] || [ -z "$b" ] && echo "yes"
$
You could make use of the following form:
[[ expression ]]
and say:
[[ -z "$a" || -z "$b" ]] && usage
This would execute usage if either a or b is empty.
Always quote your variables. Saying
[ -z $a ]
if the variable a is set to foo bar would return an error:
bash: [: foo: binary operator expected
I wrote this code:
echo -n "Enter a number1 "
echo -n "Enter a number2 "
read R1
read R2
while [ "$R1" < "$R2"]
do
if [ $((R1 % 2)) -eq 0 ]; then
$R3=$R1
echo "Number is $R3"
else
echo "Nothing"
fi
done
I don't understand why it always give me this error bash: 8]: No such file or directory
You should use -lt instead of <.
while [ "$R1" -lt "$R2" ]
< is interpreted as input redirection in bash.
Or you can use double square brackets to interpret those inside as arithmetic operation:
while [[ "$R1" < "$R2" ]]
What happens since < "$R2" is intrepreted as read from "$R2". Since you don't have a file with such a name, it complains.
[ (test command) command doesn't have < operator. You have to use -lt instead:
while [ "$R1" -lt "$R2" ]
There's a POSIX extenstion which supports it with a slash:
while [ "$R1" \< "$R2" ]
If you are using bash you bash then you can also use built-in [[ ..]] which has support for <, > etc.
while [[ "$R1" < "$R2" ]]
See also:
What is the difference between test, [ and [[ ?
After re-writing your code to put the loop inside if:
#!/bin/bash
echo -n "Enter a number1 "
read R1
echo -n "Enter a number2 "
read R2
if [[ "$R1" < "$R2" ]]
then
for((i=R1;i<R2;i++));
do
if [[ $((i % 2)) -eq 0 ]]; then
echo "Number is $i"
fi
done
else
echo "Nothing"
fi
in bash I need to compare two float numbers, one which I define in the script and the other read as paramter, for that I do:
if [[ $aff -gt 0 ]]
then
a=b
echo "xxx "$aff
#echo $CX $CY $CZ $aff
fi
but I get the error:
[[: -309.585300: syntax error: invalid arithmetic operator (error token is ".585300")
What is wrong?
Thanks
Using bc instead of awk:
float1='0.43255'
float2='0.801222'
if [[ $(echo "if (${float1} > ${float2}) 1 else 0" | bc) -eq 1 ]]; then
echo "${float1} > ${float2}"
else
echo "${float1} <= ${float2}"
fi
use awk
#!/bin/bash
num1=0.3
num2=0.2
if [ -n "$num1" -a -n "$num2" ];then
result=$(awk -vn1="$num1" -vn2="$num2" 'BEGIN{print (n1>n2)?1:0 }')
echo $result
if [ "$result" -eq 1 ];then
echo "$num1 greater than $num2"
fi
fi
Both test (which is usually linked to as [)and the bash-builtin equivalent only support integer numbers.
Use bc to check the math
a="1.21231"
b="2.22454"
c=$(echo "$a < $b" | bc)
if [ $c = '1' ]; then
echo 'a is smaller than b'
else
echo 'a is larger than b'
fi
I would use awk for that:
e=2.718281828459045
pi=3.141592653589793
if [ "yes" = "$(echo | awk "($e <= $pi) { print \"yes\"; }")" ]; then
echo "lessthanorequal"
else
echo "larger"
fi
The simplest solution is this:
f1=0.45
f2=0.33
if [[ $f1 > $f2 ]] ; then echo "f1 is greater then f2"; fi
which (on OSX) outputs:
f1 is greater then f2
Here's another example combining floating point and integer arithmetic (you need the great little perl script calc.pl that you can download from here):
dateDiff=1.9864
nObs=3
i=1
while [[ $dateDiff > 0 ]] && [ $i -le $nObs ]
do
echo "$dateDiff > 0"
dateDiff=`calc.pl $dateDiff-0.224`
i=$((i+1))
done
Which outputs
1.9864 > 0
1.7624 > 0
1.5384 > 0