Say I have a simple statement:
read number
[[ ! $number =~ ^[1-3245][,][1-3245]$ ]] && echo "Not a valid number."
I want to check to see if the number is between 1-3245. But it seems like it's looking for a number between 1 and 3 for the first integer, then 2,4,5. How do get this to check if the number entered looks like 1-3245,1-3245? I've tried with {} and .. instead of - But still no go. I'd like to avoid a crazy long string .
*Edit I should be more specific here. I am looking to check user input and match it to a desired format; that format being 'int,int,int....' where int is = an integer between 1-3245. I hope this makes sense.
CodePudding user response:
Since the base question is to write on regex to get range of numbers. So keeping it as my first solution here, for future readers help.
1st solution(using regex): With your shown samples and attempts you can have your bash script like as follows, please make sure to give script proper permissions and run it then.
Also here is the Online demo for used regex.
#!/bin/bash
echo "Enter a number:"
read number
if [[ $number =~ ^([1-9]|[1-9][0-9]{1,2}|1[0-9]{3}|2[0-9]{3}|[3][0-1][0-9]{2}|32[0-3][0-9]|324[0-5])$ ]]
then
echo "Number $number is between 1 to 3245"
else
echo "Please enter number in range of 1 to 3245..."
fi
Explanation:
- Firstly printing message on screen by
echo
command for user, its always a Good practice to put a proper user-friendly message on screen. Here in this case its "Please enter a number:" - Using
read
command to get value from user and save it intonumber
shell variable. - Then using
if
condition to match value of variable with regex^([1-9]|[1-9][0-9]{1,2}|1[0-9]{3}|2[0-9]{3}|[3][0-1][0-9]{2}|32[0-3][0-9]|324[0-5])$
, remember bash doesn't support non-capturing groups here. - if condition is TRUE then print eg:
Number 2980 is between 1 to 3245
else print eg:Please enter number in range of 1 to 3245...
2nd solution: using awk
and without regex here.
#!/bin/bash
echo "Enter a number:"
read number
val=$(echo $number | awk '$0 0==$0 && ($0>=1 && $0<=3245)')
if [[ -n "$val" ]]
then
echo "Number $number is between 1 to 3245"
else
echo "Please enter number in range of 1 to 3245..."
fi
CodePudding user response:
Assuming your criteria is: integer between 1 and 3245 (included), comma, integer between 1 and 3245 (included), you can use a mixture of regular expression and arithmetic:
$ foo() {
[[ "$1" =~ ^([0-9]*),([0-9]*)$ ]] || return 1
a=${BASH_REMATCH[1]}; b=${BASH_REMATCH[2]}
(( a >= 1 && a <= 3245 && b >= 1 && b <= 3245 ))
}
$ foo 2,2 && echo "OK" || echo "Not a valid number."
OK
$ foo 2,4000 && echo "OK" || echo "Not a valid number."
Not a valid number.
$ foo 2,bar
Not a valid number.
If the number of comma-separated integers is unknown (but minimum one) and you want to use only bash
you will need a loop:
$ foo() {
n="$1"
while [[ "$n" =~ ^([0-9] )((,[0-9] )*)$ ]] || return 1; do
(( BASH_REMATCH[1] < 1 || BASH_REMATCH[1] > 3245 )) && return 1
n="${BASH_REMATCH[2]#,}"
[[ -z "$n" ]] && return 0
done
return 1
}
$ foo 2,2,2,2,2 && echo "OK" || echo "Not a valid number."
OK
$ foo 2,2,4000,2,2 && echo "OK" || echo "Not a valid number."
Not a valid number.
$ foo 2,2,bar,2,2 && echo "OK" || echo "Not a valid number."
Not a valid number.
But if you can also use external utilities GNU awk
would be a bit simpler:
$ foo() {
awk -F, 'NR > 1 { exit 1 } {
for(i=1; i<NF; i )
if($i !~ /^[0-9] $/ || $i < 1 || $i > 3245) exit 1
}' <<< "$1"
}
$ foo 2,2,2,2,2 && echo "OK" || echo "Not a valid number."
OK
$ foo 2,2,4000,2,2 && echo "OK" || echo "Not a valid number."
Not a valid number.
$ foo 2,2,2,bar,2 && echo "OK" || echo "Not a valid number."
Not a valid number.