For bash scripting - bash

#!/bin/bash
read –p “Enter the number you seek ” NUM
for VALUE in $#; do
if [ $VALUE –eq $NUM ]; then COUNT=$((COUNT+1)); fi
done
echo $NUM appeared $COUNT times
Can the above script be modified so that :
input two inputs from the user, instead of just NUM, and count the number of parameters that are equal to or in between the two. For instance, if the user inputs 12 and 20, we would have 5 matches (12, 18, 19, 12, 18). Assume the first input is less than the second (that is, you do not need to worry about the user inputting 20 and then 12)
This is what i am coming up with:
#1/bin/bash
read - p "Enter two numbers ' NUM1 NUM2
for VALUE in $#; do
if [$VALUE <= $NUM1 ] && [ $VALUE => $NUM2 ]; then COUNT=$((COUNT+1))
fi
done
echo we have $COUNT numbers between $NUM1 and $NUM2, including $NUM1 and $NUM2

#1 is a typo for #!.
You need a space after [.
Your conditions are backwards. When value is between num1 and num2, it's greater than or equal to num1, but you have less than or equal.
The numeric comparison tests are -ge and -le, since > and < are I/O redirection operators in shell scripts.
You have to use balanced quotes around a string; if it starts with " it has to end with ", not '.
You should always quote variables unless you have a specific need to allow word splitting of the expansion.
#!/bin/bash
COUNT=0
read - p "Enter two numbers " NUM1 NUM2
for VALUE in "$#"; do
if [ "$VALUE" -ge "$NUM1" ] && [ "$VALUE" -le "$NUM2" ]; then COUNT=$((COUNT+1))
fi
done
echo "we have $COUNT numbers between $NUM1 and $NUM2, including $NUM1 and $NUM2"

Related

Check if a function return is in an interval [duplicate]

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

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

Bash script. Accept integer only if is from range

I have bash script with basic arithmetic operations - Addition, Subtraction, Division and Multiplication.
#! bin/bash
input="yes"
while [[ $input = "yes" ]]
do
PS3="Press 1 for Addition, 2 for subtraction, 3 for multiplication and 4 for division: "
select math in Addition Subtraction Multiplication Division
do
case "$math" in
Addition)
echo "Enter first no:"
read num1
echo "Enter second no:"
read num2
result=`expr $num1 + $num2`
echo Answer: $result
break
;;
Subtraction)
echo "Enter first no:"
read num1
echo "Enter second no:"
read num2
result=`expr $num1 - $num2`
echo Answer: $result
break
;;
Multiplication)
echo "Enter first no:"
read num1
echo "Enter second no:"
read num2
result=`expr $num1 * $num2`
echo Answer: $result
break
;;
Division)
echo "Enter first no:"
read num1
echo "Enter second no:"
read num2
result=$(expr "scale=2; $num1/$num2" | bc)
echo Answer = $result
break
;;
*)
echo Choose 1 to 4 only!!!!
break
;;
esac
done
done
How to make that values for #num1 and #num2 are accepted only if they are numbers in certain range. For example 0 to 10. So if I enter for $num1 or $num2 lets say 500 there will be message to enter valid value?
You can create a simple function to get a number in range:
get_number() {
local lo=$1 up=$2 text=${3:-Enter a number: } num
shopt -s extglob
until
read -p "$text" num
[[ $num = ?(-)+([0-9]) ]] && (( $lo <= 10#$num && 10#$num <= $up ))
do
echo "Invalid input!" >&2
done
echo "$((10#$num))"
}
num1=$(get_number 10 15 "Enter first number: ")
num2=$(get_number -10 20) # use default prompt
Works for integers only. You might also consider inputting the numbers before the case command to avoid redundant code.

ge vs double equal in bash

I am trying to solve a hackerrank exercise.
If n is odd, print Weird
If n is even and in the inclusive range of 2 to 5, print Not Weird
If n is even and in the inclusive range of 6 to 20, print Weird
If n is even and greater than 20, print Not Weird
My code is as follows:
read n
if [ $n%2==0 ]; then
if [ $n -ge 6 ] && [ $n -le 20 ]; then
echo "Weird"
else
echo "Not Weird"
fi
else
echo "Weird"
fi
When I give the input as 3, the result I get is Not Weird which is not correct same for 1 I get Not Weird. However, when I try this:
read n
if [ $(($n%2)) -eq 0 ]; then
if [ $n -ge 6 ] && [ $n -le 20 ]; then
echo "Weird"
else
echo "Not Weird"
fi
else
echo "Weird"
fi
I get the right result. What is the difference?
[ ] (or test) builtin:
==, or to be POSIX compliant =, does a string comparison
-eq does a numeric comparison
Note: == and -eq (and other comparisons) are parameters to the [ command, so they must be separated by whitespace, so $n%2==0 is invalid.
[[ ]] keyword:
is as [ except that it does pattern matching. Being a keyword rather than a builtin, expansion with [[ is done earlier in the scan.
(( )) syntax
Carries out arithmetic evaluation as with the let builtin. Whitespace separators are not mandatory. Using a leading $ to expand a variable is not necessary and is not recommended since it changes the expansion order.
For truth evaluation inside if-else, bash provides ((..)) operators with no need of a $ on the front.
n=5
if (( (n % 2) == 0 )); then
echo "Something"
if (( n >= 6 )) && (( n <= 20 )); then
echo "Some other thing"
else
echo "Other else thing"
fi
else
echo "Something else"
fi
Read here for more information.

Shell script read user input

I got stuck on this shell script code where it requires user to enter the group number and find the largest and the average out of that group number.
My code ATM only works with passing the group number as a command-line argument. How to prompt for the group number as user input?
read n
if [ $n -ge 1 ]; then
sum=0
count=$n
max=-1000
if [ $max -lt $1 ]; then
max=$1
fi
while [ $n -ge 1 ]; do
case $1 in
[0-9] | [1-9][0-9])
sum=`expr $sum +$1`;;
-[1-9] | -[1-9][0-9])
sum=`expr $sum + $1`;;
done
if [ $count -gt 0 ]; then
avg=`expr $sum / $count`
echo The largest number is $max
echo The average number is $avg
From your comments it seems you would like to read values from stdin rather than from the command line. To do that in Bash you use the read builtin:
read -ep "Enter group number: " group
printf "Entered %d\n" $group
For interactive prompting it is usually put in the test part of a while loop where you can break if the input is invalid:
shopt -s extglob
while read -ep "Enter group number: " group; do
case $group in
?(-)+([0-9])) # valid input
# compute average here
*) break ;; # not valid input
esac
done
See help read for more information.
You're working way too hard, and your script is way too verbose. Try:
#!/bin/sh
test $# -gt 0 || { echo Please enter at least one argument >&2; exit 1; }
max=0
for x; do
test "$max" -lt $x && max=$x
test $? -gt 1 && exit 1
: $(( count += 1 ))
: $(( sum += x ))
done
echo max = $max
printf "avg = "
expr $sum / $count
Since you used expr in your script, I'm doing the same, but be aware that all of the arithmetic will be done in the integers (so the reported average will be the greatest integer less than the actual average, and non-integer input will be considered an error). This solution relies on test returning a value greater than 1 when it encounters an error (eg, non integer input), which is the behavior specified by the open group.
Also note that this puts the error message on stderr (where error messages belong) and returns a non-zero value to indicate that the script failed.

Resources