I am programming a little number-guessing game in bash.
This is the code so far:
#!/bin/bash
#Number guessing
read -p "Who are you? " name
echo "Welcome, ${name}!"
read -p "How high do you want to guess? " level
number=$(($RANDOM % $level))
((attempts++))
while [[ ${guess} != ${number} ]]
do
read -p "Whats the number? " guess
case $guess in
$number) echo "Correct! You needed ${attempts} attempts"
break
;;
*) echo "Wrong..."
((attempts++))
;;
esac
if [[ ${guess} > ${number} ]]
then
echo "Above."
else
echo "Below."
fi
done
This asks for the users name, how high the numbers that have to be guessed go and then generates a random number based on $level. What I want to do is a echo whether the entered number was above or below the guessed number. The if at the end of the while-loop doesnt work and the same if in the last case *) echo "Wrong" doesnt work either. Is it possible to have such an if in a case in a while loop or do you have another solution?
Have a nice day
!= and > are string comparison operators inside [[ ... ]]; you want integer comparison.
while [[ ${guess} -ne ${number} ]]
if [[ ${guess} -gt ${number} ]]
or better in bash, use an arithmetic statement where you can use the normal operators.
while (( guess != number ))
if (( guess > number ))
Related
I am a beginner at unix and I am trying to use a while loop to get a user integer input for 2 numbers, but I need to check if it is an integer and reask if it's not, so I attempted to utilize if statements inside the while loop. I cannot get this to work, what am I doing wrong with the while and if loop?
#! /bin/bash
echo “Enter first number:“
while read number1
do
if[[ $number1 ]] && [ $input -eq $input 2>/dev/null ]
then
echo “$number1”
else
echo "$number1 is not an integer or not defined.Try again”
fi
done
echo “Enter second number:“
while read number2
do
if[[ $number2 ]] && [ $input -eq $input 2>/dev/null ]
then
echo “$number2”
else
echo "$number2 is not an integer or not defined.Try again”
fi
done
If you are trying to get the number and checking it until it becomes integer, Please try the below code.
#!/bin/bash
echo "enter number"
while read number1
do
if ! [[ $number1 =~ ^[0-9]+$ ]]
then
echo "number is not an integer"
else
echo "number is an integer"
exit;
fi
done
Because bash returns me that != is invalid, but it's a basic operator.
I try to use it in a three expression for loop
for (( c=1; ${!c}!=""; c++ ))
do
You can, but it's not really the usual way to check if there are empty arguments.
for((i=1; i<=$#; ++i)); do
[[ "${!i}" ]] || echo "$0: Argument $i is empty" >&2
done
If you don't care about the index, just looping over the actual arguments is even simpler.
for arg in "$#"; do
[[ "$arg" ]] || echo "$0: Empty argument" >&2
done
Notice how we print diagnostics to standard error, and take care to include the name of the script which generates the diagnostic in the message.
You very rarely need to check for empty arguments in practice, but perhaps this is a learning exercise.
You can't do string comparison in a (()) because it's only arithmetic.
What you could do is something like this, where the string check is separate test after incrementing the counter var:
c=0
while (( c += 1 )) && [[ -n ${!c} ]]; do
echo "$c ${!c}"
done
how to check both conditions in shell script, that whether a number has alphabets and that number should not consist of more than 10 digits
re='[a-zA-Z]'
read -p "Enter time:" epoch_time
if [[ "$epoch_time" =~ $re ]] -a [[ "${#time}" -gt 10 ]];then
echo "not a valid time"
else
echo "entered time is valid"
fi
You can write your regular expression to validate just for numbers and to check for input length.
re='^[0-9]+{0,10}$'; read -p "Enter time:" epoch_time
if [[ $epoch_time =~ $re ]]; then echo "entered time is valid"; else "not valid time" fi
I'm trying to make a script, just for fun which creates a new User and Generates a Password for him.
Now I have to check if the user enters something stupid, instead of a digit.
function checkifcorrectnum() {
#Check if the User did something else than enter a number
#And check if the Number is absurdly big
case "$1" in
[[:digit:]] ) if [ "$1" -gt "255" ]; then echo "Too big!" ; else : ; fi ;;
*) echo "Please enter a number!"; exit ;;
esac
}
But when I run the script, and enter 1-9 it works, but anything higher wont
You are only matching for a single digit by just [[:digit:]]. The bash globbing cannot be used like Regex and match any token any number of times by operators like * or +. If you want to stick with your method and you know exactly how many digits you want to allow then use e.g. for 2 digits:
case "$1" in
[[:digit:]][[:digit:]])
If you are not sure then:
case "$1" in
[[:digit:]]*)
* expands to any number of character.
But i think you should look at Regex matching offered by bash by the =~ operator of [[, so your whole function can be rewritten as:
if [[ $1 =~ ^[[:digit:]]+$ ]]; then
[[ $1 -gt 255 ]] && echo "Too big!"
else
echo 'Please enter a number!' && exit
fi
Also as you are not doing anything if the number is <=255 so [[ $1 -gt 255 ]] && echo "Too big!" is enough.
Since it is easier to test if a string is not a number than to test if it is, I suggest inverting the order of the tests:
function checkifcorrectnum() {
case "$1" in
*[^[:digit:]]*) echo "Please enter a number";;
*) [ "$1" -gt "255" ] && echo "Too big!" ;;
esac;
}
The glob *[^[:digit:]]* matches if any character in $1 is not a digit.
Examples:
$ checkifcorrectnum 255
$ checkifcorrectnum 256
Too big!
$ checkifcorrectnum 25z
Please enter a number
As an aside, the keyword function is bash-only and generally not necessary. With the keyword removed, the code works not only in bash but also in any POSIX compatible shell.
This question already has answers here:
Test whether string is a valid integer
(11 answers)
Closed 7 years ago.
I wrote a bash script which takes numbers for calculation via user input. The problem I have is if the user types a letter or a space by mistake, the whole script fails and the user must start again.
There must be an easy way to check the input is numeric only that will ask for the input again if anything else is input accidentally?
Use a while loop
number=""
while [[ ! $number =~ ^[0-9]+$ ]]; do
echo Please enter your age
read number
done
echo You are $number years old
And to avoid the heavy regex engine, use a simple glob:
if [[ ! $input || $input = *[^0-9]* ]]; then
echo "Error: '$input' is not a number." >&2
fi
Allows space before and after the number, _33, or 33___ , but not 3__3. and no letters.
0 or
-- Get input from user until Correct
# -- get input until Correct
unset get_num
while [[ ! ${get_num} =~ ^[0-9]+$ ]]; do
echo "Please enter in a number:"
read get_num
done
echo This is a number : ${get_num}
-- Get input until Correct (within range)
# -- get input until Correct (within range)
unset get_num
while [[ ! ${get_num} =~ ^[0-9]+$ ]]; do
echo "Please enter in a number within range of (1-30):"
read get_num
! [[ ${get_num} -ge 1 && ${get_num} -le 30 ]] && unset get_num
done
echo This is a number withn a range : ${get_num}
-- get input until Correct (within range) (full regex way)
"Since regular expressions deal with text rather than with numbers, matching a number in a given range takes a little extra care. You can't just write [0-255] to match a number between 0 and 255. Though a valid regex, it matches something entirely different. [0-255] is a character class with three elements: the character range 0-2, the character 5 and the character 5 (again). This character class matches a single digit 0, 1, 2 or 5, just like [0125]." ~ http://www.regular-expressions.info/numericranges.html
# -- get input until Correct (within range) (another way)
unset get_num
while [[ ! ${get_num} =~ ^([1-9]|1[0-9]|2[0-9]|30)$ ]]; do
echo "Please enter in a number within range of (1-30):"
read get_num
done
echo This is a number withn a range : ${get_num}
-- Get input, and check it only (no while loop)
# -- get input, and check it only (no while loop)
unset get_num
echo "Please enter in a number:"
read get_num
if [[ ! ${get_num} =~ ^[0-9]+$ ]] ;then
echo "${get_num} isn't a number"
else
echo "${get_num} is a number"
fi