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
Related
I'm just learning terminal commands, I'm trying to create my own command, but I have the following problem
./myFile: line 10: syntax error in conditional expression
./myFile: line 11: syntax error near `then'
./myFile: line 11: ` then'
there is my code
#!/bin/bash
echo "please enter name of the folder"
read NAME1
if [[ $NAME1 ]]
then
echo "enter first number"
read NUM1
if [[ $NUM1 ]] && [[ $NUM1 -ge 0]]
then
echo "enter last number"
read NUM2
if [[ $NUM2 ]] && [[ $NUM2 -gt $NUM ]]
then
mkdir $NAME1{$NUM1..$NUM2}
else
echo"please enter last number to continue"
fi
else
echo "please enter first number to continue"
fi
else
echo "please enter name of the folder to continue"
fi
Firstly, the expression [[ $NAME1 ]] is not valid, or at least, does not do what you think it does. I believe you are trying to determine if the user actually typed in a string. To do this, you should either test for a non-empty string ([[ -n ${NAME1} ]]) or test for a string length greater than zero ([[ ${#NAME1} -gt 0 ]]). The same applies when you are testing $NUM1 and $NUM2.
Secondly, when dealing with user input, you should take care to avoid testing empty strings. This is best achieved by quoting your variables. For example: [[ "${NUM1}" -gt 0 ]].
Thirdly, spaces are important in tests. always leave a space after the [[ and before the ]].
In addition, $NUM (line 15) is not declared, so will evaluate to the empty string. This should be set somewhere earlier in the script.
There are many other areas in which this script could be improved (e.g. checking for numerical input, checking for valid folder names, etc. But the above changes should get you past the immediate errors.
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.
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 ))
I can't seem to allow single integer input only.
If someone puts abc, it will work.
But if someone puts in abc123 or 123abc it will still treat it as a valid integer
# input to be an integer.
validate_integer(){
if [ ! "$#" -eq "1" ]; then
error "Please enter one numberic value only"
return 1
elif [[ "$1" =~ ^[[:alpha:]]+$ ]]; then
error "Input must be a NUMBER"
return 1
else
return 0
fi
}
Change this line:
elif [[ "$1" =~ ^[[:alpha:]]+$ ]]; then
to this:
elif ! [[ "$1" =~ ^[[:digit:]]+$ ]]; then
There, ^[[:digit:]]+$ means the string must be composed of digits from beginning to end, and it must be 1 or more characters long. We negate this with !, to handle the case when the string does not satisfy this condition (not fully numeric).