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}
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}
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: http://tldp.org/LDP/abs/html/bashver3.html#REGEXMATCHREF
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;
for __line in "${@:2}";
do
if ! [[ "$__line" =~ $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
RT or Regex Test# Declare a local variable for a loop.
declare __line;
# Loop for every argument's value except the first - regex rule
for __line in "${@:2}";
# Test the value and return a **non-zero** return code if failed.
# Alternative: if [[ ! "$__line" =~ $1 ]];
if ! [[ "$__line" =~ $1 ]];
# Return a **zero** return code - success.
return 0;
# Define arguments for the function to test
regex_v='^[0-9]*$'; # Regex rule
value_1_v='12345'; # First value
value_2_v='67890'; # Second value
# A statement which runs the function with specified arguments
# and executes `printf 'Valid';` if succeeded, else - `printf 'Invalid';`
if RT "$regex_v" "$value_v";
It should be possible to point at failed argument, for example, by appending a counter to the loop and printing its value to stderr.
The quotes around the right-hand side of the
=~operator cause it to become a string, rather than a RegularExpression.
Where the usage of a regex can be helpful to determine if the character sequence of a date is correct, it cannot be used easily to determine if the date is valid. The following examples will pass the regular expression, but are all invalid dates: 20180231, 20190229, 20190431
So if you want to validate if your date string (let's call it datestr) is in the correct format, it is best to parse it with date and ask date to convert the string to the correct format. If both strings are identical, you have a valid format and valid date.
if [[ "$datestr" == $(date -d "$datestr" "+%Y%m%d" 2>/dev/null) ]]; then
echo "Valid date"
else
echo "Invalid date"
fi