WHILE loop script - bash

I am trying to write a script that will continue to prompt a user to enter a grade, until the user enters 999.
If the user enters 90 or more, echo A. If the user enters 80 or more, echo B. If the user enters 70 or more, echo C. Otherwise echo Failed.
I am thinking this needs a WHILE script. Below is my current code
#!/bin/bash
# Asuume that the first paramter is going to be a grade
if [ $# -lt 1 ];
then
echo -n "Please pass a a grade "
fi
gr=$1
if [ $gr -ge 90 ]
then
echo "A"
elif [ $gr -ge 80 ]
then
echo "B"
elif [ $gr -ge 70 ]
then
echo "C"
else
echo "Failed"
fi
exit 0
The script prompts me, but closes after I enter 1 grade.
Thanks in advance

As you want to prompt the user to input grades until he enters 999, you should use read instead of command line arguments. As bash doesn't have a do-while loop, we can emulate it's behavior using while as shown below:
#!/bin/bash
read -p "Please pass a grade " gr
while [ $gr -ne 999 ]; do
if [ $gr -ge 90 ]
then
echo "A"
elif [ $gr -ge 80 ]
then
echo "B"
elif [ $gr -ge 70 ]
then
echo "C"
else
echo "Failed"
fi
read -p "Please pass a grade " gr
done
exit 0

That's not a prompt, it's just a message.
Prompting would be:
read -p "Please pass a grade: " gr
But this get's into conflict with your following gr=$1, so put this into an else block:
if [ $# -lt 1 ]
then
read -p "Please pass a grade: " gr
else
gr=$1
fi
Note that you don't need a semicolon at the line end; it's the line break, which can be substituted by the semicolon.
And you don't need an exit to end a script, if you don't want to exit prematurely.

Please try below code.
while true
do
read -p "Please pass a grade:" gr
if [ ${gr} -eq 999 ]
then
exit 0
elif [ ${gr} -ge 90 ]
then
echo "A"
elif [ ${gr} -ge 80 ]
then
echo "B"
elif [ ${gr} -ge 70 ]
then
echo "C"
else
echo "Failed"
fi
done

Related

Grade Calculator Script Linux assistance

Can anyone help me with my code? When I run my script I always get Grade F.
#!/bin/bash
echo "Enter your percentage to see grade letter"
read grade
if [ $grade -ge 60 ]; then
echo "Your Grade F"
elif [ $grade -ge 60 ] || [ $grade -le 69 ]; then
echo "Your grade D"
elif [ $grade -ge 70 ] && [ $grade -le 79 ]; then
echo "Your grade C"
elif [ $grade -ge 80 ] && [ $grade -le 89 ]; then
echo "Your grade B"
elif [ $grade -ge 90 ] && [ $grade -le 100 ]; then
echo "Your Grade is A"
else
echo "try again"
fi
You have a logic error in your code. Your first test is wrong. It tests all values that are greater than or equal to 60, and makes them an F. This prevents the rest of the tests from happening for those values.
Your second test is also wrong; you're using an OR (||) instead of an AND (&&).
Your last test could be reduced, because all values greater than or equal to 90 are an A, so the second test isn't necessary.
I personally would test for the higher vales and work down if I was writing the code, but that's your choice. The below should work.
#!/bin/bash
echo "Enter your percentage to see grade letter"
read grade
if [ $grade -le 59 ]; then
echo "Your Grade F"
elif [ $grade -ge 60 ] && [ $grade -le 69 ]; then
echo "Your grade D"
elif [ $grade -ge 70 ] && [ $grade -le 79 ]; then
echo "Your grade C"
elif [ $grade -ge 80 ] && [ $grade -le 89 ]; then
echo "Your grade B"
elif [ $grade -ge 90 ]; then
echo "Your Grade is A"
else
echo "try again"
fi
An alternative method using case statement could be
read -r -p 'Enter your percentage to see grade letter: ' percent
case $percent in
[0-9] | [0-5][0-9] ) echo 'Your Grade F';;
6[0-9] ) echo 'Your Grade D';;
7[0-9] ) echo 'Your Grade C';;
8[0-9] ) echo 'Your Grade B';;
9[0-9] | 100 ) echo 'Your Grade A';;
*) echo 'Try again'
esac
Here's how I'd do it.
#!/bin/bash
# Get the grade
read -rp "Enter your percentage to see grade letter: " grade
# Test the input to make sure it's a number,
# and exit with an error message if it isn't
[[ "$grade" =~ ^[0-9]+$ ]] || { echo "Please enter an integer." ; exit; }
# Test the number, print the grade, and exit
[[ "$grade" -le 49 ]] && { echo "You want to go home and re-think your life." ; exit; }
[[ "$grade" -le 59 ]] && { echo "Your Grade: F" ; exit; }
[[ "$grade" -le 69 ]] && { echo "Your grade: D" ; exit; }
[[ "$grade" -le 79 ]] && { echo "Your grade: C" ; exit; }
[[ "$grade" -le 89 ]] && { echo "Your grade: B" ; exit; }
[[ "$grade" -ge 90 ]] && { echo "Your Grade: A" ; exit; }
I'm not sure if it's more or less efficient than using if-elif-fi or case. I'm sure it's not as pretty. But it only tests $grade until it gets a hit and then it stops, and something about that appeals to me.
I was tempted to put the "Is this a number?" test in a loop so you wouldn't have to invoke the script again if you flubbed the input, but I resisted the temptation.
(I'm a rookie with bash scripting, so I welcome criticism.)

While loop in a shell script gives error : [: too many arguments. How to resolve this issue?

function read_num(){
echo "Enter a lower limit"
read lower_limit
echo "Enter a upper limit"
read upper_limit
while [ [ $lower_limit -lt 1 ] || [ $lower_limit -gt $upper_limit ] ]
do
echo "Please enter again."
read_num
done
}
read_num
when I enter the two numbers lower and upper limit it gives the following output.
check.sh: line 6: [: too many arguments
And line number 6 is while loop
while [ [ $lower_limit -lt 1 ] || [ $lower_limit -gt $upper_limit ] ]
Here you go, this works for me:
#!/bin/bash
function read_num(){
echo "Enter a lower limit"
read lower_limit
echo "Enter a upper limit"
read uper_limit
while [[ $lower_limit -lt 1 ]] || [[ $lower_limit -gt $upper_limit ]]
do
echo "Please enter again."
read_num
done
}
read_num
Reference: Bash scripting, multiple conditions in while loop

How to call another script within a script with bash

Hello here is my primary script. The test2.sh is just an echo "it worked"
what happens when I try and call from the original loop, it gets to the correct file then echo's infinite "it worked" where it should just be doing it once.
Any idea why? I really want to have another loop called outside of the main script that won't interfere, but still learning bash =P
#!/bin/bash
number=1
while true
do
if [ "$number" -eq "1" ]; then
echo "hello 1!"
elif [ "$number" -eq "2" ]; then
echo "hello 2!"
elif [ "$number" -eq "3" ]; then
echo "hello 3!"
elif [ "$number" -eq "4" ]; then
./test2.sh & continue
fi
sleep 5
((number++))
echo $number
done
first observation & is not a logical operator, & runs the precedding command in the background. Use && for logical operations.
what you need is a break keyword not a continue keyword . If you use the break keyword, the loop will stop executing. The continue keyword only rexecutes the loop , and since number is 4 , this branch of code will always run elif [ "$number" -eq "4" ]; then
working code
#!/bin/bash
number=1
while true
do
if [ "$number" -eq "1" ]; then
echo "hello 1!"
elif [ "$number" -eq "2" ]; then
echo "hello 2!"
elif [ "$number" -eq "3" ]; then
echo "hello 3!"
elif [ "$number" -eq "4" ]; then
./test2.sh && break
fi
sleep 5
((number++))
echo $number
done
or you can do this
for number in {1..4};do
(( number == 4 )) && ./test2.sh || echo "$number"
sleep 5
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

Why is my If Statement in Bash not working?

Hi I'm creating an archiving system in bash with a long and messy if statement which doesn't currently work with the current errors being on the last few lines with the else if statement. Although I expect there are further errors with this statement anyway. The variable choice is from a menu which displays in the terminal. So if they select option 1 the user then has to enter data to be written to the crontab file.
if [ $choice -eq "1" ] then
echo "Enter the MINUTE"
read minute
if [ $minute -eq 0 ] then
GLOBIGNORE=*
minute="*"
echo minute
fi
echo "Enter the Hour"
read hour
if [ $hour -eq 0 ] then
GLOBIGNORE=*
hour="*"
echo hour
fi
echo "Enter the Day"
read day
if [ $day -eq 0 ] then
GLOBIGNORE=*
day="*"
echo day
fi
echo "Enter the Month"
read month
if [ $month -eq 0 ] then
GLOBIGNORE=*
month="*"
echo month
fi
echo "Enter the weekday"
read weekday
if [ $weekday -eq 0 ] then
GLOBIGNORE=*
weekday="*"
echo weekday
fi
echo $minute $hour $day $month $weekday " date > ~/testcron.log" > testcron.txt fi
elif [ $choice -eq "2" ]
then
echo "Enter the Source and Destination Locations"
fi
There are several issues with your code:
if [ $hour -eq 0 ] then
GLOBIGNORE=*
hour="*"
echo hour
fi
In general (all test []) are missing a ; after it:
if [ $hour -eq 0 ]; then
The echo hour will not print the value of var hour but the word hour. Change to echo "$hour" (yes, quoted). Also, there is no need to set the variable GLOBIGNORE to * if vars are properly quoted.
The vars here are not quoted, that is a reason for it to fail (or to need GLOBIGNORE):
echo $minute $hour $day $month $weekday
Change to:
echo "$minute $hour $day $month $weekday"
The redirection on that same line is a plain >, that will empty the file.
If you want to append to the files, do as this:
echo "$minute $hour $day $month $weekday" "$(date >> ~/testcron.log)" >>testcron.txt
In that line there is an unneeded additional fi
This script may be of help:
get(){
read -p "$1" "$2"
if [ "$((${!2}))" -eq 0 ]; then
eval "$2"="*"
echo "${!2}"
fi
}
read -p "Choice?:" choice
if [ "$choice" -eq "1" ]; then
get "Enter the MINUTE" minute
get "Enter the Hour" hour
get "Enter the Day" day
get "Enter the Month" month
get "Enter the weekday" weekday
date >> ~/testcron.log
echo "$minute $hour $day $month $weekday" >> testcron.txt
elif [ "$choice" -eq "2" ]; then
echo "Enter the Source and Destination Locations"
fi
You are missing a semi-colon:
if [ $choice -eq "1" ]; then
or
if [ $choice -eq "1" ]
then
A semi-colon or a newline is required because the command is actually [ and has to be terminated after the ], which is just the last argument given to [.
That is the old test (or [) syntax, you could also use:
if (( choice == 1 ))
then

Resources