Validating number of arguments - bash

I apologize for the beginners question ahead of time but I cannot get this chunk of code to work properly. I was asked to make a basic program which asks the user for 3 numbers and then checks which is the highest value and prints the results, as well as makes sure there are three numbers put in. It can determine which is his highest and im getting it to output results properly but I cant seem to figure out how to get it to validate that there are three numbers put in.
I have done research and even pulled some code from the teachers example about how to check the number of arguments but I still cant get it to work.
#!/bin/bash
echo "Please enter three numbers:"
read a b c
if [ $# -ne 3 ]
then
echo "You need three numbers"
exit -1
fi
if [ $a -gt $b -a $a -gt $c ]
then
LARGEST=$a
elif [ $b -gt $a -a $b -gt $c ]
then
LARGEST=$b
elif [ $c -gt $a -a $c -gt $b ]
then
LARGEST=$c
elif [ $a -eq $b -a $a -eq $c -a $b -eq $c -eq $b ]
then
LARGEST="All three values are equal."
fi
echo "The largest values is $LARGEST"
When I enter three numbers (7 8 9) I expect to get back:
"The largest value is 9"
however I get this instead:
./values.sh: line 6 [0: command not found
The largest value is 9
Am i missing something blatantly obvious here? I know i need an operator to make my original if statement work but am i using the wrong one?

The [ -z "$c" ] test solves it for the code you posted.
Working code:
#!/bin/bash
echo "Please enter three numbers:"
read a b c d
if [ -z "$c" ]
then
echo "You need three numbers"
exit -1
fi
if [ -n "$d" ]
then
echo "enter only three numbers"
exit -1
fi
if [ $a -gt $b -a $a -gt $c ]
then
LARGEST=$a
elif [ $b -gt $a -a $b -gt $c ]
then
LARGEST=$b
elif [ $c -gt $a -a $c -gt $b ]
then
LARGEST=$c
elif [ $a -eq $b -a $a -eq $c -a $b -eq $c -eq $b ]
then
LARGEST="All three values are equal."
fi
echo "The largest values is $LARGEST"
Output:
$ ./t.sh
Please enter three numbers:
7 8
You need three numbers
$ ./t.sh
Please enter three numbers:
7 8 9
The largest values is 9

Related

Why is the execution of my binary search script not proceeding after input?

I wrote a shell script for binary search of integers. It's accepting space separated integer array, but when the code proceeds and we input the element to be searched, the code doesn't proceed further. It is either stuck or it is accepting more inputs, both of which is undesired.
Here's the code:
#!/bin/bash
declare -a arr
echo "Enter space separated sorted integers:"
read -ra arr
declare -i search
echo -n "Enter the element to be searched for: "
read -r search
index=-1
beg=0
mid=0
last=${#arr[#]}
last=$((last - 1))
while [ $beg -le $last ]; do
mid=$((beg / 2 + end / 2))
if [ $mid -eq "$search" ]; then
index=$mid
break
elif [ $mid -gt "$search" ]; then
end=$((mid - 1))
elif [ $mid -lt "$search" ]; then
beg=$((mid + 1))
fi
done
if [ $index -ne -1 ]; then
echo "Element found at $index"
else
echo "Element not found"
fi
Ok, so here are the errors I found in my code:
using end instead of last (Thanks to John Kugelman, EdmCoff, markp-fuso)
Never actually comparing Array values as in Array[index] (Thanks to markp-fuso)
sometimes, mid=$((beg / 2 + last / 2)) won't behave as mid=(beg + last)/2. Sometimes when beg, last=5, beg/2 + last/2 will evaluate in 4 instead of 5.
Last but not least, using echo in debugging always helps, (Thanks to chepner )
So final working code looks like:
#!/bin/bash
declare -a arr
echo "Enter space separated sorted integers:"
read -ra arr
declare -i search
echo -n "Enter the element to be searched for: "
read -r search
index=-1
beg=0
mid=0
last=${#arr[#]}
last=$((last - 1))
while [ $beg -le $last ]; do
echo -e "\nbeg=$beg\nmid=$mid\nlast=$last\n"
mid=$((beg + last))
mid=$((mid/2))
if [ "${arr[$mid]}" -eq "$search" ]; then
index=$mid
break
elif [ "${arr[$mid]}" -gt "$search" ]; then
last=$((mid - 1))
elif [ "${arr[$mid]}" -lt "$search" ]; then
beg=$((mid + 1))
fi
done
if [ $index -ne -1 ]; then
echo "Element found at $((index+1))"
else
echo "Element not found"
fi

How to check if a number is within a range in shell

I want to just insert number between two values, and otherwise the script repeated until correct number.
This is my script and it does not work correctly:
validation(){
read number
if [ $number -ge 2 && $number -ls 5 ]; then
echo "valid number"
break
else
echo "not valid number, try again"
fi
}
echo "insert number"
validation
echo "your number is" $number
If you are using Bash, you are better off using the arithmetic expression, ((...)) for readability and flexibility:
if ((number >= 2 && number <= 5)); then
# your code
fi
To read in a loop until a valid number is entered:
#!/bin/bash
while :; do
read -p "Enter a number between 2 and 5: " number
[[ $number =~ ^[0-9]+$ ]] || { echo "Enter a valid number"; continue; }
if ((number >= 2 && number <= 5)); then
echo "valid number"
break
else
echo "number out of range, try again"
fi
done
((number >= 2 && number <= 5)) can also be written as ((2 <= number <= 5)).
See also:
Test whether string is a valid integer
How to use double or single brackets, parentheses, curly braces
Your if statement:
if [ $number -ge 2 && $number -ls 5 ]; then
should be:
if [ "$number" -ge 2 ] && [ "$number" -le 5 ]; then
Changes made:
Quoting variables is considered good practice.
ls is not a valid comparison operator, use le.
Separate single-bracket conditional expressions with &&.
Also you need a shebang in the first line of your script: #!/usr/bin/env bash
if [ $number -ge 2 && $number -ls 5 ]; then
should be
if [[ $number -ge 2 && $number -le 5 ]]; then
see help [[ for details
Try bellow code
echo "Enter number"
read input
if [[ $input ]] && [ $input -eq $input 2>/dev/null ]
then
if ((input >= 1 && input <= 4)); then
echo "Access Granted..."
break
else
echo "Wrong code"
fi
else
echo "$input is not an integer or not defined"
fi
2 changes needed.
Suggested by Sergio.
if [ "$number" -ge 2 ] && [ "$number" -le 5 ]; then
There is no need of break. only meaningful in a for, while, or until loop
while :; do
read option
if [[ $option -ge 1 && $option -lt 4 ]]; then
echo "correct"
c
break
else
echo "Incorrect option selected,choose an option between [1-4]"
fi
done

script for testing if number is in interval

I am trying to test if a number is in the interval [1;100] here is what I did:
var=10
if [ $["$var" -gt "1" ] -a $["$var" -lt "100"] ] ; then
echo "yes"
else
echo "no"
fi
however when I run the script I get the error message:
./yourscript:line 2 10 -gt 1:error syntax in expression ,any ideas why?
delete unnecessaries and use &&:
var=10
if [ $var -gt 1 ] && [ $var -lt 100 ] ; then #or with -a if [ $var -gt 1 -a $var -lt 100 ] ;
echo "yes"
else
echo "no"
fi

unix all if statements in one place

I am newly learning shell script ! i tried following code but i have error
line 15: syntax error near unexpected token `elif
#!/bin/bash
read -p "Enter the number : " n
if [ $n -eq 1 ]
then
echo "$n is equal to 1 true"
elif [ $n -lt 4 ]
then
echo "$n is less than value of 4 ture"
else
echo "$n is not less then value of 4 false"
elif [ $n -gt 10 ]
then
echo "$n is greater than the value of 10 true"
else
echo "$n is not greater than the value of 10 false"
if [ $n -ge 0 ]
then
echo "$n is greater than or equal to 0"
else
echo "$n is not greater than or equal to 0"
fi
else
"Bye"
fi
Can anyone help ?
It's a bit hard to tell what your intention is. The correct answer depends on what you want to do here. My guess is that you want this:
if [ $n -eq 1 ]
then
echo "$n is equal to 1 true"
elif [ $n -lt 4 ]
then
echo "$n is less than value of 4 true"
elif [ $n -gt 10 ]
then
echo "$n is greater than the value of 10 true"
elif [ $n -ge 0 ]
then
# This will be true if $n is >= 4 and <= 10
echo "$n is greater than or equal to 0"
else
# Negative
"Bye"
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

Resources