Check if a string matches a regex in Bash script

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