Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a regular expression for Cron statement

Tags:

regex

I need to write an regular expression that matches Cron time expressions, like these ones:

  • 28 2 7 1 1
  • 28 2 7 1 *
  • 28 2 7 * *
  • 28 2 * * *
  • 28 * * * *
  • * * * * *
like image 357
irishman Avatar asked Jan 07 '13 19:01

irishman


People also ask

What is the use of * * * * * In cron?

It is a wildcard for every part of the cron schedule expression. So * * * * * means every minute of every hour of every day of every month and every day of the week .


1 Answers

To validate cron expressions in general, it'll depend greatly on the specific implementation you're using

Rules

General Format

In general, most adhere to the the following format:

Field name Mandatory? Allowed values Special characters
Seconds No* 0-59 * / , -
Minutes Yes 0-59 * / , -
Hours Yes 0-23 * / , -
Day of month Yes 1-31 * / , - L W
Month Yes 1-12 or JAN-DEC * / , -
Day of week Yes 0-6 or SUN-SAT * / , - L #
Year No* 1970–2099 * / , -

*where seconds and years are non-standard and sometimes not included

Predefined Scheduling Macros:

Some flavors allow predefined time periods like this:

Entry Equivalent to
@annually 0 0 0 1 1 * *
@yearly 0 0 0 1 1 * *
@monthly 0 0 0 1 * * *
@weekly 0 0 0 * * 0 *
@daily 0 0 0 * * * *
@hourly 0 0 * * * * *
@reboot

Intervals

Some flavors allow using the @every <duration> syntax with the following timespan units:

Unit Definition
ns nanosecond
us, µs microsecond
ms millisecond
s second
m minute
h hour

Validating

Predefined Macros Regex

To validate predefined macros, you can use the following regex:

/@(annually|yearly|monthly|weekly|daily|hourly|reboot)/

Which will pass the following test cases:

@daily
@hourly

@every Regex

To validate @every durations, you can use the following regex:

/@every (\d+(ns|us|µs|ms|s|m|h))+/

Which will pass the following test cases:

@every 5s
@every 20h30m

Individual Cron Terms

Validating cron terms in the regular expression is a little trickier since there are so many variations.

Just focusing in on a single term, the following are all valid:

  • Two or more numbers separated by a ,
  • Two numbers separated by a / or -
  • A 1-2 digit number
  • A single *

To validate a single term, we can use the following regex:

/(\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*/

where \d+ just guarantees you have 1 or more numeric digits

Which will pass the following test cases:

1,2,3
1,2
1/2
1-2
1
*

Combining Cron Terms

To check the full expression, we can just make sure we have {5,7} terms with the following regex:

/(((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*) ?){5,7}/

If we wanted to distinguish between each term, we'd need to validate numbers within a certain range:

Allowed values Regex
0-59 [1-5]?[0-9]
0-23 2[0-3]|1[0-9]|[0-9]
1-31 3[01]|[12][0-9]|[1-9]
1-12 1[0-2]|[1-9]
0-6 [0-6]
1970–2099 19[7-9][0-9]|20[0-9][0-9]

If however, we just want to make sure something looks like a regex expression without worrying about which term is days vs. hours, the expression stays a lot cleaner, so that's what I'll go with for simplicity

Putting it all together

By combining the above statements, we can have a relatively simple sanity check that the term looks regex-y with the following expression:

/(@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(@every (\d+(ns|us|µs|ms|s|m|h))+)|((((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*) ?){5,7})/

Additional Resources

  • crontab.guru
  • regexr.com
like image 67
KyleMit Avatar answered Sep 17 '22 21:09

KyleMit