Check If a String Matches a Regex in Bash Script
One of the Arguments That My Script Receives Is a Date in the Following Format: Yyyymmdd. I Want to Check If I Get a Valid Date as an Input. How Can I Do This?...
One of the arguments that my script receives is a date in the following format: yyyymmdd.
I want to check if I get a valid date as an input.
How can I do this? I am trying to use a regex like: [0-9]\{\8}
5 Answers
You can use the test construct, [[ ]], along with the regular expression match operator, =~, to check if a string matches a regex pattern (documentation).
For your specific case, you can write:
[[ "$date" =~ ^[0-9]{8}$ ]] && echo "yes"
Or more a accurate test:
[[ "$date" =~ ^[0-9]{4}(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])$ ]] && echo "yes"
# |\______/\______*______/\______*__________*______/|
# | | | | |
# | | | | |
# | --year-- --month-- --day-- |
# | either 01...09 either 01..09 |
# start of line or 10,11,12 or 10..29 |
# or 30, 31 |
# end of line
That is, you can define a regex in Bash matching the format you want. This way you can do:
[[ "$date" =~ ^regex$ ]] && echo "matched" || echo "did not match"
where commands after && are executed if the test is successful, and commands after || are executed if the test is unsuccessful.
Note this is based on the solution by Aleks-Daniel Jakimenko in User input date format verification in bash.
In other shells you can use grep. If your shell is POSIX compliant, do
(echo "$date" | grep -Eq ^regex$) && echo "matched" || echo "did not match"
In fish, which is not POSIX-compliant, you can do
echo "$date" | grep -Eq "^regex\$"; and echo "matched"; or echo "did not match"
Caveat: These portable grep solutions are not water-proof! For example, they can be tricked by input parameters that contain newlines. The first mentioned bash-specific regex check does not have this issue.
In bash version 3 you can use the '=~' operator:
if [[ "$date" =~ ^[0-9]{8}$ ]]; then
echo "Valid date"
else
echo "Invalid date"
fi
Reference:
NOTE: The quoting in the matching operator within the double brackets, [[ ]], is no longer necessary as of Bash version 3.2
A good way to test if a string is a correct date is to use the command date:
if date -d "${DATE}" >/dev/null 2>&1
then
# do what you need to do with your date
else
echo "${DATE} incorrect date" >&2
exit 1
fi
from comment: one can use formatting
if [ "2017-01-14" == $(date -d "2017-01-14" '+%Y-%m-%d') ]
In addition to other answers of the =~ Bash operator - Extended Regular Expressions (ERE).
This is the syntax used by
awkandegrep(orgrep -E),
as well as by Bash's[[ ... =~ ... ]]operator.
For example, a function which supports multiple test provided in multiple arguments:
#!/bin/bash
#-----------#
# Functions #
#-----------#
function RT
{
declare line_l;
for line_l in "${@:2}";
do
if ! [[ "$line_l" =~ $1 ]];
then
return 1;
fi
done
return 0;
}
#-----------#
# Main #
#-----------#
regex_v='^[0-9]*$';
value_1_v='12345';
value_2_v='67890';
if RT "$regex_v" "$value_1_v" "$value_2_v";
then
printf 'Valid';
else
printf 'Invalid';
fi
Description
Function RT or Regex Test
# Declare a local variable for a loop.
declare line_l;
# Loop for every argument's value except the first whish is a regex rule
for line_l in "${@:2}";
# Test the value and return a **non-zero** return code if failed
if ! [[ "$line_l" =~ $1 ]];
# Return a **zero** return code - success.
return 0;