22

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 * * * *
  • * * * * *
EnzoR
  • 3,107
  • 2
  • 22
  • 25
irishman
  • 272
  • 1
  • 2
  • 7

15 Answers15

66

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

KyleMit
  • 30,350
  • 66
  • 462
  • 664
  • 4
    You're missing "every x minutes", e.g. [https://crontab.guru/#*/5_*_*_*_*](https://crontab.guru/#*/5_*_*_*_*). Might be better to change the 3rd form to `([\d\*]+(\/|-)\d+)` – Jerry Chong Mar 03 '20 at 09:30
  • 1
    day names and month names are missing – Chiptus Jun 18 '20 at 14:51
  • 2
    From @JerryChong comment, it gives `/(@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(@every (\d+(ns|us|µs|ms|s|m|h))+)|((((\d+,)+\d+|([\d\*]+(\/|-)\d+)|\d+|\*) ?){5,7})/`, and will support notations containing "every x minuts" like `*/5 * * * *` – Mtxz Jan 29 '21 at 02:59
  • this doesn't support "0-20/2" (every 2nd minute/hour from 0 through 20). see https://crontab.guru/#0-20/2_*_*_*_* – Fre Timmerman Jul 01 '22 at 07:05
  • This is just checking some basic stuff. You can rely on this, e.g. * * 30 * * * is an invalid expression but due to regex provided here it's valid. – Sanan Guliyev Mar 19 '23 at 11:02
15

I just finished writing one, so here is mine, hope it helps.

This should allow the * or */num and also limit the number values to their logical range (1-12 for months, 0-24 for hours, and so on)

/^(\*|([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])|\*\/([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])) (\*|([0-9]|1[0-9]|2[0-3])|\*\/([0-9]|1[0-9]|2[0-3])) (\*|([1-9]|1[0-9]|2[0-9]|3[0-1])|\*\/([1-9]|1[0-9]|2[0-9]|3[0-1])) (\*|([1-9]|1[0-2])|\*\/([1-9]|1[0-2])) (\*|([0-6])|\*\/([0-6]))$/
wonea
  • 4,783
  • 17
  • 86
  • 139
Petar Zivkovic
  • 970
  • 10
  • 20
  • 2
    This is great, though I ran into trouble with commas. This regex rejects an expression such as `0 3,15 * * *`. – kbrimington May 24 '16 at 15:47
  • 4
    Thanks! Although I think your expression can be abbreviated to: `/^(\*|((\*\/)?[1-5]?[0-9])) (\*|((\*\/)?[1-5]?[0-9])) (\*|((\*\/)?(1?[0-9]|2[0-3]))) (\*|((\*\/)?([1-9]|[12][0-9]|3[0-1]))) (\*|((\*\/)?([1-9]|1[0-2]))) (\*|((\*\/)?[0-6]))$/` (without losing any meaning) – michel404 Jun 02 '16 at 18:43
  • Thanks for the input, I haven't really put much effort into refactoring the expression but I'm positive it can be improved on! – Petar Zivkovic Jun 03 '16 at 09:44
  • 1
    This will work for the basic cases, but if you were to specify something like 5 1 * * 1-5 (1:05 on weekdays) the regex doesnt work. In that case you would need to modify it to something like:^(\*|([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])|\*\/([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])) (\*|([0-9]|1[0-9]|2[0-3])|\*\/([0-9]|1[0-9]|2[0-3])) (\*|([1-9]|1[0-9]|2[0-9]|3[0-1])|\*\/([1-9]|1[0-9]|2[0-9]|3[0-1])) (\*|([1-9]|1[0-2])|\*\/([1-9]|1[0-2])) (\*|[0-6]*\-[0-6]|[0-6])$ – CraigAlbright Aug 06 '19 at 15:34
6

Took me a while :D it validates based on this documentation: http://en.wikipedia.org/wiki/Cron However it doesn't take into account that you cannot specify day of week and day of month, ie you can specify both according to this regex. This can be used for boost::regex

    (((([*])|(((([0-5])?[0-9])((-(([0-5])?[0-9])))?)))((/(([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?[0-9])))?))(,(((([*])|(((([0-5])?[0-9])((-(([0-5])?[0-9])))?)))((/(([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?[0-9])))?)))* (((([*])|(((((([0-1])?[0-9]))|(([2][0-3])))((-(((([0-1])?[0-9]))|(([2][0-3])))))?)))((/(([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?[0-9])))?))(,(((([*])|(((((([0-1])?[0-9]))|(([2][0-3])))((-(((([0-1])?[0-9]))|(([2][0-3])))))?)))((/(([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?[0-9])))?)))* (((((((([*])|(((((([1-2])?[0-9]))|(([3][0-1]))|(([1-9])))((-(((([1-2])?[0-9]))|(([3][0-1]))|(([1-9])))))?)))((/(([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?[0-9])))?))|(L)|(((((([1-2])?[0-9]))|(([3][0-1]))|(([1-9])))W))))(,(((((([*])|(((((([1-2])?[0-9]))|(([3][0-1]))|(([1-9])))((-(((([1-2])?[0-9]))|(([3][0-1]))|(([1-9])))))?)))((/(([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?[0-9])))?))|(L)|(((((([1-2])?[0-9]))|(([3][0-1]))|(([1-9])))W)))))*)|([?])) (((([*])|((((([1-9]))|(([1][0-2])))((-((([1-9]))|(([1][0-2])))))?))|((((JAN)|(FEB)|(MAR)|(APR)|(MAY)|(JUN)|(JUL)|(AUG)|(SEP)|(OKT)|(NOV)|(DEC))((-((JAN)|(FEB)|(MAR)|(APR)|(MAY)|(JUN)|(JUL)|(AUG)|(SEP)|(OKT)|(NOV)|(DEC))))?)))((/(([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?[0-9])))?))(,(((([*])|((((([1-9]))|(([1][0-2])))((-((([1-9]))|(([1][0-2])))))?))|((((JAN)|(FEB)|(MAR)|(APR)|(MAY)|(JUN)|(JUL)|(AUG)|(SEP)|(OKT)|(NOV)|(DEC))((-((JAN)|(FEB)|(MAR)|(APR)|(MAY)|(JUN)|(JUL)|(AUG)|(SEP)|(OKT)|(NOV)|(DEC))))?)))((/(([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?[0-9])))?)))* (((((((([*])|((([0-6])((-([0-6])))?))|((((SUN)|(MON)|(TUE)|(WED)|(THU)|(FRI)|(SAT))((-((SUN)|(MON)|(TUE)|(WED)|(THU)|(FRI)|(SAT))))?)))((/(([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?[0-9])))?))|((([0-6])L))|(W)|(([#][1-5]))))(,(((((([*])|((([0-6])((-([0-6])))?))|((((SUN)|(MON)|(TUE)|(WED)|(THU)|(FRI)|(SAT))((-((SUN)|(MON)|(TUE)|(WED)|(THU)|(FRI)|(SAT))))?)))((/(([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?[0-9])))?))|((([0-6])L))|(W)|(([#][1-5])))))*)|([?]))((( (((([*])|((([1-2][0-9][0-9][0-9])((-([1-2][0-9][0-9][0-9])))?)))((/(([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?[0-9])))?))(,(((([*])|((([1-2][0-9][0-9][0-9])((-([1-2][0-9][0-9][0-9])))?)))((/(([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?([0-9])?[0-9])))?)))*))?)
Martin Kosicky
  • 471
  • 4
  • 12
4

Regex for full cron expression

  • handles 'L' and '#' cases correctly.
  • day and month specific text ranges
  • still allow any value for number, month names and week days
/^((((\d+,)+\d+|(\d+(\/|-|#)\d+)|\d+L?|\*(\/\d+)?|L(-\d+)?|\?|[A-Z]{3}(-[A-Z]{3})?) ?){5,7})$/

Test it at: https://regexr.com/5bdes

With non capturing groups

Using (?: for hidding the groups.

^(?:(?:(?:(?:\d+,)+\d+|(?:\d+(?:\/|-|#)\d+)|\d+L?|\*(?:\/\d+)?|L(?:-\d+)?|\?|[A-Z]{3}(?:-[A-Z]{3})?) ?){5,7})$

Putting it all together

/^((((\d+,)+\d+|(\d+(\/|-|#)\d+)|\d+L?|\*(\/\d+)?|L(-\d+)?|\?|[A-Z]{3}(-[A-Z]{3})?) ?){5,7})$|(@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(@every (\d+(ns|us|µs|ms|s|m|h))+)/

Some test cases

# At 12:00 pm (noon) every day during the year 2017:
0 0 12 * * ? 2017
# Every 5 minutes starting at 1 pm and ending on 1:55 pm and then starting at 6 pm and ending at 6:55 pm, every day:
0 0/5 13,18 * * ?
# Every minute starting at 1 pm and ending on 1:05 pm, every day:
0 0-5 13 * * ?
# At 1:15 pm and 1:45 pm every Tuesday in the month of June:
0 15,45 13 ? 6 Tue
# At 9:30 am every Monday, Tuesday, Wednesday, Thursday, and Friday:
0 30 9 ? * MON-FRI
# At 9:30 am on 15th day of every month:
0 30 9 15 * ?
# At 6 pm on the last day of every month:
0 0 18 L * ?
# At 6 pm on the 3rd to last day of every month:
0 0 18 L-3 * ?
# At 10:30 am on the last Thursday of every month:
0 30 10 ? * 5L
# At 6 pm on the last Friday of every month during the years 2015, 2016 and 2017:
0 0 18 ? * 6L 2015-2017
# At 10 am on the third Monday of every month:
0 0 10 ? * 2#3
# At 12 am midnight on every day for five days starting on the 10th day of the month:
0 0 0 10/5 * ?
Juarez Rudsatz
  • 369
  • 3
  • 7
  • Thank you so much for the RegExp, but there is a bug: `$` sign is placed to incorrect position: that regexp works well for me: `/^((((\d+,)+\d+|(\d+(\/|-|#)\d+)|\d+L?|\*(\/\d+)?|L(-\d+)?|\?|[A-Z]{3}(-[A-Z]{3})?) ?){5,7})|(@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(@every (\d+(ns|us|µs|ms|s|m|h))+)$/` – slava Sep 27 '22 at 11:29
1

It's hard to make an exact regex without knowing which program you'll use to run it, but this should work:

(28|\*) (2|\*) (7|\*) (1|\*) (1|\*)
  • 11
    This probably worked well for the original poster, but this would work terribly for crontab matching. – senfo Aug 26 '16 at 16:08
  • @EnzoR I wrote this answer quite a while ago, and wrote it to match the OP's question in the body (before your edit, it asked for "all of these possibilities in a string", which this answer does, and included OP's attempt, which was a regex intended to match exactly the strings as above). Unfortunately, I cannot delete it, as it's the accepted answer. Feel free to downvote if you haven't already. I agree that's it's not a very useful answer, and I'll try to improve it when I have the time. – Reinstate Monica -- notmaynard Jan 23 '20 at 16:40
1

To avoid a very long line, you may split the cron string then match each field with below patterns. Value range, step and comma groups are supported!

// minute: 0-59
/^(\*|[1-5]?[0-9](-[1-5]?[0-9])?)(\/[1-9][0-9]*)?(,(\*|[1-5]?[0-9](-[1-5]?[0-9])?)(\/[1-9][0-9]*)?)*$/

// hour: 0-23
/^(\*|(1?[0-9]|2[0-3])(-(1?[0-9]|2[0-3]))?)(\/[1-9][0-9]*)?(,(\*|(1?[0-9]|2[0-3])(-(1?[0-9]|2[0-3]))?)(\/[1-9][0-9]*)?)*$/

// monthDay: 1-31
/^(\*|([1-9]|[1-2][0-9]?|3[0-1])(-([1-9]|[1-2][0-9]?|3[0-1]))?)(\/[1-9][0-9]*)?(,(\*|([1-9]|[1-2][0-9]?|3[0-1])(-([1-9]|[1-2][0-9]?|3[0-1]))?)(\/[1-9][0-9]*)?)*$/

// month: 1-12
/^(\*|([1-9]|1[0-2]?)(-([1-9]|1[0-2]?))?)(\/[1-9][0-9]*)?(,(\*|([1-9]|1[0-2]?)(-([1-9]|1[0-2]?))?)(\/[1-9][0-9]*)?)*$/

// weekDay: 0-6
/^(\*|[0-6](-[0-6])?)(\/[1-9][0-9]*)?(,(\*|[0-6](-[0-6])?)(\/[1-9][0-9]*)?)*$/

It cannot verify the range boudary, i.e. 0,*/3,6-1/20 is acceptable here

A very useful site that might help: https://crontab.guru/

clarkttfu
  • 577
  • 6
  • 11
1

Here's my solution, as I found this question and the answers didn't suit my purpose. This .NET regex conditionally parses a 5-7 part cron statement, includes (afaik) most of the special characters I've seen and will only populate the correct captures (seconds in seconds group, etc) for any length. It also doesn't try to validate the digits of the dates input, ie. you can input the 67th minute, that is more verbose and I simplified for readability. It's also not anchored anywhere and you might need some lazy matching to the end of the line to cleanly capture multiples, but i stripped that out so as not to confuse.

You'll want this as multi-line, ignore whitespace, explicit capture.

((?<seconds>\*|([0-5]?[0-9])((-|,|\/)?([0-5]?[0-9])?)+)[ \t]+)?(?#seconds)
(?<minutes>\*|([0-5]?[0-9])((-|,|\/)?([0-5]?[0-9])?)+)[ \t]+(?#minutes)
(?<hours>\*|([0-2]?[0-9])((-|,|\/)?([0-2]?[0-9])?)+)[ \t]+(?#hours)
(?<dom>\*|\?|L|([1-2]?[0-9])((-|,|\/)?([1-2]?[0-9])?)+)\s(?#dayofmonth)
(?<month>((\*)|(1?[0-9])|(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))((\/|,|-|\#)((\*)|(1?[0-9])|(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)))?)\s(?#month)
(?<dow>(\*|\?|L|(MON|TUE|WED|THU|FRI|SAT|SUN)|[1-7])((-|,|\/|L|W|C|\#)?((MON|TUE|WED|THU|FRI|SAT|SUN)|[1-7])?)+)\s(?#day of week)
(?(seconds)(?<year>([1-2][0-9]{3})((,|-|\/)([1-2][0-9]{3}))?)?)(?#year, cond on seconds match)
hcp
  • 486
  • 1
  • 3
  • 11
1

@KyleMit answer's is a great place to start, but I found out that his regex is also catching some invalid use-cases like:

  • *-* * * * *
  • *1 * 1 * *
  • 1* * 1 * *

So I updated his regex:

/(^((\*\/)?([0-5]?[0-9])((\,|\-|\/)([0-5]?[0-9]))*|\*)\s+((\*\/)?((2[0-3]|1[0-9]|[0-9]|00))((\,|\-|\/)(2[0-3]|1[0-9]|[0-9]|00))*|\*)\s+((\*\/)?([1-9]|[12][0-9]|3[01])((\,|\-|\/)([1-9]|[12][0-9]|3[01]))*|\*)\s+((\*\/)?([1-9]|1[0-2])((\,|\-|\/)([1-9]|1[0-2]))*|\*|(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|des))\s+((\*\/)?[0-6]((\,|\-|\/)[0-6])*|\*|00|(sun|mon|tue|wed|thu|fri|sat))\s*$)|@(annually|yearly|monthly|weekly|daily|hourly|reboot)/

and now it is working as expected.

eyarz
  • 136
  • 5
1

you can use the following Regular expression and use the test method on your input to check if the input is valid or not.

pattern: new RegExp(
        /^((\*(?!(-))|([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])|\*\/([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])(?!(-)))(?!(-\d-)))(([-]{1}(\*(?!(-))|[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]))|([,]{1}(\*(?!(-))|[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|\*\/([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])(?!(-))))(?!(-\d-)))* ((\*(?!(-))|([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])|\*\/([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])(?!(-)))(?!(-\d-)))(([-]{1}(\*(?!(-))|[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]))|([,]{1}(\*(?!(-))|[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|\*\/([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])(?!(-))))(?!(-\d-)))* ((\*(?!(-))|([0-9]|1[0-9]|2[0-3])|\*\/([0-9]|1[0-9]|2[0-3])(?!(-)))(?!(-\d-)))(([-]{1}(\*(?!(-))|[0-9]|1[0-9]|2[0-3]))|([,]{1}(\*(?!(-))|[0-9]|1[0-9]|2[0-3]|\*\/([0-9]|1[0-9]|2[0-3])(?!(-))))(?!(-\d-)))* ((\*(?!(-))|([1-9]|1[0-9]|2[0-9]|3[0-1])|\*\/([1-9]|1[0-9]|2[0-9]|3[0-1])(?!(-)))(?!(-\d-)))(([-]{1}(\*(?!(-))|[1-9]|1[0-9]|2[0-9]|3[0-1]))|([,]{1}(\*(?!(-))|[1-9]|1[0-9]|2[0-9]|3[0-1]|\*\/([1-9]|1[0-9]|2[0-9]|3[0-1])(?!(-))))(?!(-\d-)))* ((\*(?!(-))|([1-9]|1[0-2])|\*\/([1-9]|1[0-2])(?!(-)))(?!(-\d-)))(([-]{1}(\*(?!(-))|[1-9]|1[0-2]))|([,]{1}(\*(?!(-))|[1-9]|1[0-2]|\*\/([1-9]|1[0-2])(?!(-))))(?!(-\d-)))* ((\*(?!(-))|([0-6])|\*\/([0-6])(?!(-)))(?!(-\d-)))(([-]{1}(\*(?!(-))|[0-6]))|([,]{1}(\*(?!(-))|[0-6]|\*\/([0-6])(?!(-))))(?!(-\d-)))*$/
      ), 

It's developed based on the below format: 'second[0-59] minute[0-59] hour[0-23] day-of-month[1-31] month[1-12] day-of-week[0-6]'

For instance, if you use something like *,*/5,5-10 5-6,10-12 20 2 * 3-4 in your input and run the pattern.test(your input variable), you will get true result.

Generally the above regular expression work properly, but if you use bigger number-small number, such as 4-3, the result will get true in the final result which is not acceptable. So, to resolve this issue, you can use the following function too for the onkeyup or onblur attributes of your input and make it equal to the following function name, like "dashCheck" to check this case as well.

dashCheck() {
  let dashNumber = 0;
  let text = your input name.pattern;
  if (text.match(/-/g)) {
    dashNumber = text.match(/-/g).length;
  }
  
  let x = -1;
  for (let i = 0; i < dashNumber; ++i) {
    x = text.indexOf("-", x + 1);
    if (isNaN(text[x + 2]) === false && text[x + 2] !== " ") {
      if (isNaN(text[x - 2]) === false) {
        if (text.slice(x + 1, x + 3) >= text.slice(x - 2, x)) {
        } else {
          return false;
        }
      } else {
      }
    } else if (isNaN(text[x + 1]) === false) {
      if (isNaN(text[x - 2]) === false && text[x - 2] !== " ") {
        return false;
      } else {
        if (text.slice(x + 1, x + 2) >= text.slice(x - 1, x)) {
        } else {
          return false;
        }
      }
    }
  }
  return true;
}

Now, if you use the regular expression and call the above function both, your cronjob will be perfectly checked and worked.

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
1

for the people who wanna validate allowed value

^(((([1-5]?[0-9],)+[1-5]?[0-9]|([1-5]?[0-9](\/|-)[1-5]?[0-9](\/\d+)?)|[1-5]?[0-9]|\*(\/\d+)?) )((([1-5]?[0-9],)+[1-5]?[0-9]|([1-5]?[0-9](\/|-)[1-5]?[0-9](\/\d+)?)|[1-5]?[0-9]|\*(\/\d+)?) )((((2[0-3]|1[0-9]|[0-9]),)+(2[0-3]|1[0-9]|[0-9])|((2[0-3]|1[0-9]|[0-9])(\/|-)(2[0-3]|1[0-9]|[0-9])(\/\d+)?)|(2[0-3]|1[0-9]|[0-9])|\*(\/\d+)?) )((((3[01]|[12][0-9]|[1-9]),)+(3[01]|[12][0-9]|[1-9])|((3[01]|[12][0-9]|[1-9])(\/|-)(3[01]|[12][0-9]|[1-9])(\/\d+)?)|(3[01]|[12][0-9]|[1-9])|\*(\/\d+)?) )((((1[0-2]|[1-9]),)+(3[01]|[12][0-9]|[1-9])|((1[0-2]|[1-9])(\/|-)(1[0-2]|[1-9])(\/\d+)?)|(1[0-2]|[1-9])|[A-Z]{3}|\*(\/\d+)?) )((([0-6],)+[0-6]|([0-6](\/|-)[0-6]((\/|-)\d+)?)|[0-6]|\*(\/\d+)?|[A-Z]{3}?)))$|(@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(@every (\d+(ns|us|µs|ms|s|m|h))+)
Blinko
  • 11
  • 3
0

Your current regex will only match 5 characters, since each character class can only match a single character. For each position you either want to match the number or *, with one or more spaces between each position, you can do that with the following:

(28|\*) +[2*] +[7*] +[1*] +[1*]

Note that since the first number has two digits, you need to use alternation instead of a character class.

You will probably also want to add some anchors to your regex so that it doesn't match just part of a string, if this is necessary add ^ to the beginning and $ to the end.

Andrew Clark
  • 202,379
  • 35
  • 273
  • 306
0

do the simplest thing that could possibly work

"^28 2 7 1 1$|^28 2 7 1 \*$|^28 2 7 \* \*$|^28 2 \* \* \*$|^28 \* \* \* \*$|^\* \* \* \* \*$"

http://rubular.com/r/Z0hfT5X9K8

0

Not sure if this can help somebody, but here are some regex to check time parameter values without the feature for writing out the names of weekdays.

//string validation
function allowed_characters($value, $mode){
    switch ($mode) {
        case '0': //0-59
            $preg_code = "^(((([0-5]?[0-9]|60)(-([0-5]?[0-9]|60)){0,1}?)|\*)(,([0-5]?[0-9]|60)((-([0-5]?[0-9]|60)){0,1}?))*?)$";
            break;
        case '1': //0-23
            $preg_code = "^(((([0-1]?[0-9]|2[0-4])(-([0-1]?[0-9]|2[0-4])){0,1}?)|\*)(,([0-1]?[0-9]|2[0-4])((-([0-1]?[0-9]|2[0-4])){0,1}?))*?)$";
            break;
        case '2': //1-31
            $preg_code = "^(((([0-2]?[0-9]|3[0-1])(-([0-2]?[0-9]|3[0-1])){0,1}?)|\*)(,([0-2]?[0-9]|3[0-1])((-([0-2]?[0-9]|3[0-1])){0,1}?))*?)$";
            break;
        case '3': //0-12
            $preg_code = "^(((([0]?[0-9]|1[0-2])(-([0]?[0-9]|1[0-2])){0,1}?)|\*)(,([0]?[0-9]|1[0-2])((-([0]?[0-9]|1[0-2])){0,1}?))*?)$";
            break;
        case '4': //0-6
            $preg_code = "^(((([0]?[[0-7])(-([0]?[0-7])){0,1}?)|\*)(,([0]?[0-7])((-([0]?[0-7])){0,1}?))*?)$";
            break;
        default:
            return false;
            break;
    }
0

Regex for a single expression (still simple but powerful)

^(?:(?:(?:\d+-\d+\/\d+|\d+(?:[-,\/]\d+)?|\*\/\d+)(?:,(?:\d+-\d+\/\d+|\d+(?:[-,\/]\d+)?|\*\/\d+))*)|\*)$
Andre Elrico
  • 10,956
  • 6
  • 50
  • 69
0
^(((?:[1-9]?\d|\*)(\/[0-9]{1,2}){0,1}\s){4}(?:([1-9]?\d|\*)(\/[0-9]{1,2}){0,1}|(MON)|(TUE)|(WED)|(THU)|(FRI)|(SAT)|(SUN))){1}$
General Grievance
  • 4,555
  • 31
  • 31
  • 45