- Crond表达式正则解析
- 一. Crond表达式
- 二. Crond结构
- 三. Crond表达式分域正则解析
- 3.1 秒
- 3.1.1 `秒域`的有效写法
- 3.1.2 `秒域`的无效写法
- 3.1.3 正则适配如下
- 3.1.4 `秒域`完整写法如下:
- 3.2 分
- 3.3 时
- 3.3.1 `时域`的有效写法
- 3.3.2 `时域`的无效写法
- 3.3.3 正则适配如下
- 3.3.4 `时域`完整写法如下:
- 3.4 日
- 3.4.1 `日域`的有效写法
- 3.4.2 `日域`的无效写法
- 3.4.3 正则适配如下
- 3.4.4 `日域`完整写法如下:
- 3.5 月
- 3.5.1 `月域`的有效写法
- 3.5.2 `月域`的无效写法
- 3.5.3 正则适配如下
- 3.5.4 `月域`完整写法如下:
- 3.6 周
- 3.6.1 `周域`的有效写法
- 3.6.2 `周域`的无效写法
- 3.6.3 正则适配如下
- 3.6.4 `周域`完整写法如下:
- 3.7 年
- 3.7.1 `年域`的有效写法
- 3.7.2 `年域`的无效写法
- 3.7.3 正则适配如下==没有严格适配年份, 用4个数字代替==
- 3.7.4 `年域`完整写法如下:
- 四. Crond表达式完整正则解析
- 五. Java校验Crond表达式
Cron表达式是一个字符串, 表示一个执行周期, 常用于Linux的Crond, 或Java开发的QuartZ定时任务框架等. 可参考Crond表达式解析.
二. Crond结构Cron表达式是一个字符串, 字符串中由空格隔开, 分为6或7个域, 每一个域代表一个含义, 语法格式如下, 可参考Crond表达式解析:
| * | * | * | * | * | * | * |
|---|---|---|---|---|---|---|
| 秒 | 分 | 时 | 日 | 月 | 周 | 年 |
| Seconds | Minutes | Hours | DayOfMonth | Month | DayOfWeek | Year |
| 必选 | 必选 | 必选 | 必选 | 必选 | 必选 | 可选 |
| 0 ~ 59整数 | 0 ~ 59整数 | 0 ~ 23整数 | 1 ~ 31整数 (随月份而定) | 1 ~ 12整数 JAN ~ DEC月份 | 1 ~ 7整数 SUN ~ SAT (1=SUN) | 1970~2099 |
3.1.2 秒域的无效写法
- 第一种: 每秒执行1次, 写法 * 或 */1
- 第二种: 每3秒执行1次, 写法 */3
- 第三种: 从第2秒开始到第10秒, 每秒执行1次, 写法 2-10 或 2-10/1 或 2,3,4,5,6,7,8,9,10
- 第四种: 从第2秒开始到第10秒, 每3秒执行1次, 写法 2-10/3
- 第五种: 从第2秒开始到第10秒, 第22秒开始到第30秒, 每3秒执行1次, 写法 2-10,22-30/3
- 其他
3.1.3 正则适配如下
- 第四种: 从第2秒开始到第10秒, 每3秒执行1次, 无效写法 2,3,4,5,6,7,8,9,10/3 或 2-8,9,10/3
根据上述有效写法, 规整, 拆分正则表达如下, 域最后必须有至少 1个 空格 结尾:
- 第一组, 带有 * 号, 有效写法有 * 或 */x, x是1-59的数字, 正则写法: (?:*(?:/(?:[1-9]|[1-5][0-9])){0,1}s{1,})
- 第二组, 一个纯数字, 有效写法 y, y是0-59的数字 或 y/x, y是0-59的数字, x是1-59的数字, 正则写法 (?:[0-5]{0,1}[0-9]{1}(?:/(?:[1-9]|[1-5][0-9])){0,1}s{1,})
- 第三组, 数字 带有 , 和 - 号, 不含 / 号, 有效写法有 12,13 或 12-13 或 12,13-23,55 或 12-15,18-23,55, 正则写法: (?:[0-5]{0,1}[0-9]{1}(?:-[0-5]{0,1}[0-9]{1}){0,1}(?:,(?:[0-5]{0,1}[0-9]{1}(?:-[0-5]{0,1}[0-9]{1}){0,1})){0,}s{1,})
- 逻辑1: 必定以一个数字开头
- 逻辑2: 开头数字后面可以链接 -
- 逻辑3: 从第2组开始, 通过链接 , 接下一组, 重复第1组的逻辑
- 第四组, 数字 带有 - 号 和 , 号 和 / 号, 有效写法 1-5/1 或 1-5,7-10/1, 无效写法 1,2-5/1, 正则写法: (?:[0-5]{0,1}[0-9]{1}-[0-5]{0,1}[0-9]{1}(?:,[0-5]{0,1}[0-9]{1}-[0-5]{0,1}[0-9]{1}){0,}/(?:[1-9]|[1-5][0-9])s{1,})
- 注意 第一组和第二组可以合并写成: (?:(?:*|[0-5]{0,1}[0-9]{1})(?:/(?:[1-9]|[1-5][0-9])){0,1}s{1,})
- 非捕获组写法: (?:(?:(?:(?:*|[0-5]{0,1}[0-9]{1})(?:/(?:[1-9]|[1-5][0-9])){0,1})|(?:[0-5]{0,1}[0-9]{1}(?:-[0-5]{0,1}[0-9]{1}){0,1}(?:,(?:[0-5]{0,1}[0-9]{1}(?:-[0-5]{0,1}[0-9]{1}){0,1})){0,})|(?:[0-5]{0,1}[0-9]{1}-[0-5]{0,1}[0-9]{1}(?:,[0-5]{0,1}[0-9]{1}-[0-5]{0,1}[0-9]{1}){0,}/(?:[1-9]|[1-5][0-9])))s{1,})
- 捕获组写法: (?:((?:(?:*|[0-5]{0,1}[0-9]{1})(?:/(?:[1-9]|[1-5][0-9])){0,1})|(?:[0-5]{0,1}[0-9]{1}(?:-[0-5]{0,1}[0-9]{1}){0,1}(?:,(?:[0-5]{0,1}[0-9]{1}(?:-[0-5]{0,1}[0-9]{1}){0,1})){0,})|(?:[0-5]{0,1}[0-9]{1}-[0-5]{0,1}[0-9]{1}(?:,[0-5]{0,1}[0-9]{1}-[0-5]{0,1}[0-9]{1}){0,}/(?:[1-9]|[1-5][0-9])))s{1,})
3.3 时 3.3.1 时域的有效写法同秒域写法相同.
3.3.2 时域的无效写法
- 第一种: 每小时都执行, 写法 * 或 */1
- 第二种: 每隔3时时执行1次, 写法 */3
- 第三种: 从6时开始到10时, 每小时执行1次, 写法 6-10 或 6-10/1 或 6,7,8,9,10
- 第四种: 从6时开始到10时, 每隔2小时执行1次, 写法 6-10/2
- 第五种: 从6时开始到10时, 15时开始到18时, 每隔2小时执行1次, 写法 6-10,15-18/2
- 其他
3.3.3 正则适配如下
- 第一种: 从6时开始到10时, 每隔2小时执行1次, 无效写法 6,7,8,9,10/2 或 6-8,9,10/2
根据上述有效写法, 规整, 拆分正则表达如下, 域最后必须有至少 1个 空格 结尾:
- 第一组, 带有 * 号, 有效写法有 * 或 */x, x是1-23的数字, 正则写法: (?:*(?:/(?:[1-9]|1[0-9]|2[0-3])){0,1}s{1,})
- 第二组, 一个纯数字, 有效写法 y, y是0-23的数字 或 y/x, y是0-23的数字, x是1-23的数字, 正则写法 (?:(?:[0-9]|1[0-9]|2[0-3])(?:/(?:[1-9]|1[0-9]|2[0-3])){0,1}s{1,})
- 第三组, 数字 带有 , 和 - 号, 不含 / 号, 有效写法有 12,13 或 12-13 或 12,13-17,22 或 12-15,18-20,22, 正则写法: (?:(?:[0-9]|1[0-9]|2[0-3])(?:-(?:[0-9]|1[0-9]|2[0-3])){0,1}(?:,(?:(?:[0-9]|1[0-9]|2[0-3])(?:-(?:[0-9]|1[0-9]|2[0-3])){0,1})){0,}s{1,})
- 逻辑1: 必定以一个数字开头
- 逻辑2: 开头数字后面可以链接 -
- 逻辑3: 从第2组开始, 通过链接 , 接下一组, 重复第1组的逻辑
- 第四组, 数字 带有 - 号 和 , 号 和 / 号, 有效写法 1-5/1 或 1-5,7-10/1, 无效写法 1,2-5/1, 正则写法: (?:(?:[0-9]|1[0-9]|2[0-3])-(?:[0-9]|1[0-9]|2[0-3])(?:,(?:[0-9]|1[0-9]|2[0-3])-(?:[0-9]|1[0-9]|2[0-3])){0,}/(?:[1-9]|1[0-9]|2[0-3])s{1,})
- 注意 第一组和第二组可以合并写成: (?:(?:*|[0-9]|1[0-9]|2[0-3])(?:/(?:[1-9]|1[0-9]|2[0-3])){0,1}s{1,})
- 非捕获组写法: (?:(?:(?:(?:*|[0-9]|1[0-9]|2[0-3])(?:/(?:[1-9]|1[0-9]|2[0-3])){0,1})|(?:(?:[0-9]|1[0-9]|2[0-3])(?:-(?:[0-9]|1[0-9]|2[0-3])){0,1}(?:,(?:(?:[0-9]|1[0-9]|2[0-3])(?:-(?:[0-9]|1[0-9]|2[0-3])){0,1})){0,})|(?:(?:[0-9]|1[0-9]|2[0-3])-(?:[0-9]|1[0-9]|2[0-3])(?:,(?:[0-9]|1[0-9]|2[0-3])-(?:[0-9]|1[0-9]|2[0-3])){0,}/(?:[1-9]|1[0-9]|2[0-3])))s{1,})
- 捕获组写法: (?:((?:(?:*|[0-9]|1[0-9]|2[0-3])(?:/(?:[1-9]|1[0-9]|2[0-3])){0,1})|(?:(?:[0-9]|1[0-9]|2[0-3])(?:-(?:[0-9]|1[0-9]|2[0-3])){0,1}(?:,(?:(?:[0-9]|1[0-9]|2[0-3])(?:-(?:[0-9]|1[0-9]|2[0-3])){0,1})){0,})|(?:(?:[0-9]|1[0-9]|2[0-3])-(?:[0-9]|1[0-9]|2[0-3])(?:,(?:[0-9]|1[0-9]|2[0-3])-(?:[0-9]|1[0-9]|2[0-3])){0,}/(?:[1-9]|1[0-9]|2[0-3])))s{1,})
3.4.2 日域的无效写法
- 第一种: 每天都执行, 写法 * 或 */1
- 第二种: 每隔3天执行1次, 写法 */3
- 第三种: 从每月6日开始到10日执行, 写法 6-10 或 6-10/1 或 6,7,8,9,10
- 第四种: 从每月6日开始到10日, 每隔2日执行, 写法 6-10/2
- 第五种: 从每月6日开始到10日, 15日开始到18日, 每隔2日执行, 写法 6-10,15-18/2
- 第六种: 每月最后一天, 写法 L, 有些工具不支持些选项, 例如部分 crond
- 第七种: 每月 XX 号最近的工作日, 写法 XXW, 有些工具不支持些选项, 例如部分 crond
- 其他
3.4.3 正则适配如下
- 第一种: 从每月6日开始到10日, 每隔2日执行, 无效写法 6,7,8,9,10/2 或 6-8,9,10/2
根据上述有效写法, 规整, 拆分正则表达如下, 域最后必须有至少 1个 空格 结尾:
- 第一组, 带有 * 号, 有效写法有 * 或 */x, x是1-31的数字, 正则写法: (?:*(?:/(?:[1-9]|[1-2][0-9]|3[0-1])){0,1}s{1,})
- 第二组, 一个纯数字, 有效写法 y, y是0-31的数字 或 y/x, y是0-31的数字, x是1-31的数字, 正则写法 (?:(?:[0-9]|[1-2][0-9]|3[0-1])(?:/(?:[1-9]|[1-2][0-9]|3[0-1])){0,1}s{1,})
- 第三组, 数字 带有 , 和 - 号, 不含 / 号, 有效写法有 12,13 或 12-13 或 12,13-17,22 或 12-15,18-20,22, 正则写法: (?:(?:[0-9]|[1-2][0-9]|3[0-1])(?:-(?:[0-9]|[1-2][0-9]|3[0-1])){0,1}(?:,(?:(?:[0-9]|[1-2][0-9]|3[0-1])(?:-(?:[0-9]|[1-2][0-9]|3[0-1])){0,1})){0,}s{1,})
- 逻辑1: 必定以一个数字开头
- 逻辑2: 开头数字后面可以链接 -
- 逻辑3: 从第2组开始, 通过链接 , 接下一组, 重复第1组的逻辑
- 第四组, 数字 带有 - 号 和 , 号 和 / 号, 有效写法 1-5/1 或 1-5,7-10/1, 无效写法 1,2-5/1, 正则写法: (?:(?:[0-9]|[1-2][0-9]|3[0-1])-(?:[0-9]|[1-2][0-9]|3[0-1])(?:,(?:[0-9]|[1-2][0-9]|3[0-1])-(?:[0-9]|[1-2][0-9]|3[0-1])){0,}/(?:[1-9]|[1-2][0-9]|3[0-1])s{1,})
- 第五组, L 或 XXW, 有效写法有 L 或 1W 或 31W, 正则写法: (?:(?:L|(?:[0-9]|[1-2][0-9]|3[0-1])W)s{1,})
- 注意 第一组和第二组可以合并写成: (?:(?:*|(?:[0-9]|[1-2][0-9]|3[0-1]))(?:/(?:[1-9]|[1-2][0-9]|3[0-1])){0,1}s{1,})
- 非捕获组写法: (?:(?:L|(?:[0-9]|[1-2][0-9]|3[0-1])W|(?:(?:*|(?:[0-9]|[1-2][0-9]|3[0-1]))(?:/(?:[1-9]|[1-2][0-9]|3[0-1])){0,1})|(?:(?:[0-9]|[1-2][0-9]|3[0-1])(?:-(?:[0-9]|[1-2][0-9]|3[0-1])){0,1}(?:,(?:(?:[0-9]|[1-2][0-9]|3[0-1])(?:-(?:[0-9]|[1-2][0-9]|3[0-1])){0,1})){0,})|(?:(?:[0-9]|[1-2][0-9]|3[0-1])-(?:[0-9]|[1-2][0-9]|3[0-1])(?:,(?:[0-9]|[1-2][0-9]|3[0-1])-(?:[0-9]|[1-2][0-9]|3[0-1])){0,}/(?:[1-9]|[1-2][0-9]|3[0-1])))s{1,})
- 捕获组写法: (?:(L|(?:[0-9]|[1-2][0-9]|3[0-1])W|(?:(?:*|(?:[0-9]|[1-2][0-9]|3[0-1]))(?:/(?:[1-9]|[1-2][0-9]|3[0-1])){0,1})|(?:(?:[0-9]|[1-2][0-9]|3[0-1])(?:-(?:[0-9]|[1-2][0-9]|3[0-1])){0,1}(?:,(?:(?:[0-9]|[1-2][0-9]|3[0-1])(?:-(?:[0-9]|[1-2][0-9]|3[0-1])){0,1})){0,})|(?:(?:[0-9]|[1-2][0-9]|3[0-1])-(?:[0-9]|[1-2][0-9]|3[0-1])(?:,(?:[0-9]|[1-2][0-9]|3[0-1])-(?:[0-9]|[1-2][0-9]|3[0-1])){0,}/(?:[1-9]|[1-2][0-9]|3[0-1])))s{1,})
3.5.2 月域的无效写法
- 第一种: 每月都执行, 写法 * 或 */1
- 第二种: 每隔3月执行, 写法 */3
- 第三种: 从6月开始到10月, 每月执行, 写法 6-10 或 6-10/1 或 6,7,8,9,10
- 第四种: 从6月开始到10月, 每隔2月执行, 写法 6-10/2
- 第五种: 从3月开始到6月, 8月开始到12月, 每隔2月执行, 写法 3-6,8-12/2
- 其他
3.5.3 正则适配如下
- 第一种: 从6月开始到10月, 每隔2月执行, 无效写法 6,7,8,9,10/2 或 6-8,9,10/2
根据上述有效写法, 规整, 拆分正则表达如下, 域最后必须有至少 1个 空格 结尾:
- 第一组, 带有 * 号, 有效写法有 * 或 */x, x是1-12的数字, 正则写法: (?:*(?:/(?:[1-9]|1[0-2])){0,1}s{1,})
- 第二组, 一个纯数字, 有效写法 12 或 JAN 或 y/x, y是0-12的数字或是JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC中的一个, x是1-12的数字, 正则写法 (?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:/(?:[1-9]|1[0-2])){0,1}s{1,})
- 第三组, 数字 带有 , 和 - 号, 不含 / 号, 有效写法有 2,3 或 2-5 或 1,5-7,11 或 1-5,8-10,12, 正则写法: (?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,1}(?:,(?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,1})){0,}s{1,})
- 逻辑1: 必定以一个数字开头
- 逻辑2: 开头数字后面可以链接 -
- 逻辑3: 从第2组开始, 通过链接 , 接下一组, 重复第1组的逻辑
- 第四组, 数字 带有 - 号 和 , 号 和 / 号, 有效写法 1-5/1 或 1-5,7-10/1, 无效写法 1,2-5/1, 正则写法: (?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:,(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,}/(?:[1-9]|1[0-2])s{1,})
- 注意 英文单词缩写包含: JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC
- 注意 第一组和第二组可以合并写成: (?:(?:*|[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:/(?:[1-9]|1[0-2])){0,1}s{1,})
- 非捕获组写法: (?:(?:(?:(?:*|[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:/(?:[1-9]|1[0-2])){0,1})|(?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,1}(?:,(?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,1})){0,})|(?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:,(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,}/(?:[1-9]|1[0-2])))s{1,})
- 捕获组写法: (?:((?:(?:*|[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:/(?:[1-9]|1[0-2])){0,1})|(?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,1}(?:,(?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,1})){0,})|(?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:,(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,}/(?:[1-9]|1[0-2])))s{1,})
3.6.2 周域的无效写法
- 第一种: 每周都执行, 写法 * 或 */1
- 第二种: 每隔3周执行, 写法 */3
- 第三种: 从第1周开始到第第3周, 每周执行, 写法 1-3 或 1-3/1 或 1,2,3
- 第四种: 从第1周开始到第4周, 每隔2周执行, 写法 1-4/2
- 第五种: 从第1周开始到第2周, 第3周开始到第4周, 每隔2周执行, 写法 1-2,3-4/2
- 其他
3.6.3 正则适配如下
- 第一种: 从第1周开始到第3周, 每隔2周执行, 无效写法 1,2,3/2 或 1-2,3/2
根据上述有效写法, 规整, 拆分正则表达如下, 域最后必须有至少 1个 空格 结尾:
- 第一组, 带有 * 号, 有效写法有 * 或 */x, x是1-6的数字, 正则写法: (?:*(?:/[1-6]){0,1}s{1,})
- 第二组, 一个纯数字, 有效写法 1 或 MON 或 y/x, y是0-7的数字或是SUN|MON|TUE|WED|THU|FRI|SAT中的一个, x是1-6的数字, 正则写法 (?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:/[1-6]){0,1}s{1,})
- 第三组, 数字 带有 , 和 - 号, 不含 / 号, 有效写法有 2,3 或 2-5 或 1,3-4,7 或 1-3,4-5,6, 正则写法: (?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,1}(?:,(?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,1})){0,}s{1,})
- 逻辑1: 必定以一个数字开头
- 逻辑2: 开头数字后面可以链接 -
- 逻辑3: 从第2组开始, 通过链接 , 接下一组, 重复第1组的逻辑
- 第四组, 数字 带有 - 号 和 , 号 和 / 号, 有效写法 1-5/1 或 1-5,7-10/1, 无效写法 1,2-5/1, 正则写法: (?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:,(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,}/[1-6]s{1,})
- 注意 英文单词缩写包含: SUN|MON|TUE|WED|THU|FRI|SAT
- 注意 第一组和第二组可以合并写成: (?:(?:*|[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:/[1-6]){0,1}s{1,})
- 非捕获组写法: (?:(?:(?:(?:*|[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:/[1-6]){0,1})|(?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,1}(?:,(?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,1})){0,})|(?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:,(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,}/[1-6]))s{1,})
- 捕获组写法: (?:((?:(?:*|[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:/[1-6]){0,1})|(?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,1}(?:,(?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,1})){0,})|(?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:,(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,}/[1-6]))s{1,})
3.7.2 年域的无效写法
- 第〇种: 不指定, 写法 ? 或 不填
- 第一种: 每年都执行, 写法 * 或 */1
- 第二种: 每隔3年执行1次, 写法 */3
- 第三种: 从2000年开始到2002年执行, 写法 2000-2002 或 2000-2002/1 或 2000,2001,2002
- 第四种: 从2000年开始到2005年, 每隔2年执行, 写法 2000-2005/2
- 第五种: 从2000年开始到2005年, 20008年开始到2020年, 每隔2年执行, 写法 2000-2005,2008-2020/2
- 其他
3.7.3 正则适配如下没有严格适配年份, 用4个数字代替
- 第一种: 从2000年开始到2005年, 每隔2年执行, 无效写法 2000,2002,2003-2005/2 或 2000-2004,2005/2
根据上述有效写法, 规整, 拆分正则表达如下, 域最后必须有至少 1个 空格 结尾:
- 第〇组, 带有 ? 号, 有效写法 ?, 正则写法 (?:?s{1,})
- 第一组, 带有 * 号, 有效写法有 * 或 */x, x是数字, 正则写法: (?:*(?:/d{1,4}){0,1}s{1,})
- 第二组, 一个纯数字, 有效写法 y, y是1970-2099的数字 或 y/x, y是1970-2099的数字, x是数字, 正则写法没有适配年份: (?:d{4}(?:/d{1,4}){0,1}s{1,})
- 第三组, 数字 带有 , 和 - 号, 不含 / 号, 有效写法有 2000,2001 或 2000-2003 或 2000,2001-2003,2005, 正则写法: (?:d{4}(?:-d{4}){0,1}(?:,(?:d{4}(?:-d{4}){0,1})){0,}s{1,})
- 逻辑1: 必定以一个数字开头
- 逻辑2: 开头数字后面可以链接 -
- 逻辑3: 从第2组开始, 通过链接 , 接下一组, 重复第1组的逻辑
- 第四组, 数字 带有 - 号 和 , 号 和 / 号, 有效写法 2000-2005/1 或 2000-2005,2006-2008/1, 无效写法 2000,2001-2005/1, 正则写法: (?:d{4}-d{4}(?:,d{4}-d{4}){0,}/d{1,4}s{1,})
- 注意 第一组和第二组可以合并写成: (?:(?:*|d{4})(?:/d{1,4}){0,1}s{1,})
- 非捕获组写法: (?:(?:?|(?:(?:*|d{4})(?:/d{1,4}){0,1})|(?:d{4}(?:-d{4}){0,1}(?:,(?:d{4}(?:-d{4}){0,1})){0,})|(?:d{4}-d{4}(?:,d{4}-d{4}){0,}/d{1,4}))s{1,})
- 捕获组写法: (?:(?|(?:(?:*|d{4})(?:/d{1,4}){0,1})|(?:d{4}(?:-d{4}){0,1}(?:,(?:d{4}(?:-d{4}){0,1})){0,})|(?:d{4}-d{4}(?:,d{4}-d{4}){0,}/d{1,4}))s{1,})
注意: 在将各个域拼接时, 会适当的调整一下下正则, 不能完全拷贝.
四. Crond表达式完整正则解析
不含命令部分
- 非捕获组写法: ^(?:(?:(?:(?:*|[0-5]{0,1}[0-9]{1})(?:/(?:[1-9]|[1-5][0-9])){0,1})|(?:[0-5]{0,1}[0-9]{1}(?:-[0-5]{0,1}[0-9]{1}){0,1}(?:,(?:[0-5]{0,1}[0-9]{1}(?:-[0-5]{0,1}[0-9]{1}){0,1})){0,})|(?:[0-5]{0,1}[0-9]{1}-[0-5]{0,1}[0-9]{1}(?:,[0-5]{0,1}[0-9]{1}-[0-5]{0,1}[0-9]{1}){0,}/(?:[1-9]|[1-5][0-9])))s{1,})(?:(?:(?:(?:*|[0-5]{0,1}[0-9]{1})(?:/(?:[1-9]|[1-5][0-9])){0,1})|(?:[0-5]{0,1}[0-9]{1}(?:-[0-5]{0,1}[0-9]{1}){0,1}(?:,(?:[0-5]{0,1}[0-9]{1}(?:-[0-5]{0,1}[0-9]{1}){0,1})){0,})|(?:[0-5]{0,1}[0-9]{1}-[0-5]{0,1}[0-9]{1}(?:,[0-5]{0,1}[0-9]{1}-[0-5]{0,1}[0-9]{1}){0,}/(?:[1-9]|[1-5][0-9])))s{1,})(?:(?:(?:(?:*|[0-9]|1[0-9]|2[0-3])(?:/(?:[1-9]|1[0-9]|2[0-3])){0,1})|(?:(?:[0-9]|1[0-9]|2[0-3])(?:-(?:[0-9]|1[0-9]|2[0-3])){0,1}(?:,(?:(?:[0-9]|1[0-9]|2[0-3])(?:-(?:[0-9]|1[0-9]|2[0-3])){0,1})){0,})|(?:(?:[0-9]|1[0-9]|2[0-3])-(?:[0-9]|1[0-9]|2[0-3])(?:,(?:[0-9]|1[0-9]|2[0-3])-(?:[0-9]|1[0-9]|2[0-3])){0,}/(?:[1-9]|1[0-9]|2[0-3])))s{1,})(?:(?:L|(?:[0-9]|[1-2][0-9]|3[0-1])W|(?:(?:*|(?:[0-9]|[1-2][0-9]|3[0-1]))(?:/(?:[1-9]|[1-2][0-9]|3[0-1])){0,1})|(?:(?:[0-9]|[1-2][0-9]|3[0-1])(?:-(?:[0-9]|[1-2][0-9]|3[0-1])){0,1}(?:,(?:(?:[0-9]|[1-2][0-9]|3[0-1])(?:-(?:[0-9]|[1-2][0-9]|3[0-1])){0,1})){0,})|(?:(?:[0-9]|[1-2][0-9]|3[0-1])-(?:[0-9]|[1-2][0-9]|3[0-1])(?:,(?:[0-9]|[1-2][0-9]|3[0-1])-(?:[0-9]|[1-2][0-9]|3[0-1])){0,}/(?:[1-9]|[1-2][0-9]|3[0-1])))s{1,})(?:(?:(?:(?:*|[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:/(?:[1-9]|1[0-2])){0,1})|(?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,1}(?:,(?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,1})){0,})|(?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:,(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,}/(?:[1-9]|1[0-2])))s{1,})(?:(?:(?:(?:*|[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:/[1-6]){0,1})|(?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,1}(?:,(?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,1})){0,})|(?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:,(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,}/[1-6]))s{0})(?:(?:?|(?:(?:*|d{4})(?:/d{1,4}){0,1})|(?:d{4}(?:-d{4}){0,1}(?:,(?:d{4}(?:-d{4}){0,1})){0,})|(?:d{4}-d{4}(?:,d{4}-d{4}){0,}/d{1,4}))){0,1}s*$
- 捕获组写法: ^(?:((?:(?:*|[0-5]{0,1}[0-9]{1})(?:/(?:[1-9]|[1-5][0-9])){0,1})|(?:[0-5]{0,1}[0-9]{1}(?:-[0-5]{0,1}[0-9]{1}){0,1}(?:,(?:[0-5]{0,1}[0-9]{1}(?:-[0-5]{0,1}[0-9]{1}){0,1})){0,})|(?:[0-5]{0,1}[0-9]{1}-[0-5]{0,1}[0-9]{1}(?:,[0-5]{0,1}[0-9]{1}-[0-5]{0,1}[0-9]{1}){0,}/(?:[1-9]|[1-5][0-9])))s{1,})(?:((?:(?:*|[0-5]{0,1}[0-9]{1})(?:/(?:[1-9]|[1-5][0-9])){0,1})|(?:[0-5]{0,1}[0-9]{1}(?:-[0-5]{0,1}[0-9]{1}){0,1}(?:,(?:[0-5]{0,1}[0-9]{1}(?:-[0-5]{0,1}[0-9]{1}){0,1})){0,})|(?:[0-5]{0,1}[0-9]{1}-[0-5]{0,1}[0-9]{1}(?:,[0-5]{0,1}[0-9]{1}-[0-5]{0,1}[0-9]{1}){0,}/(?:[1-9]|[1-5][0-9])))s{1,})(?:((?:(?:*|[0-9]|1[0-9]|2[0-3])(?:/(?:[1-9]|1[0-9]|2[0-3])){0,1})|(?:(?:[0-9]|1[0-9]|2[0-3])(?:-(?:[0-9]|1[0-9]|2[0-3])){0,1}(?:,(?:(?:[0-9]|1[0-9]|2[0-3])(?:-(?:[0-9]|1[0-9]|2[0-3])){0,1})){0,})|(?:(?:[0-9]|1[0-9]|2[0-3])-(?:[0-9]|1[0-9]|2[0-3])(?:,(?:[0-9]|1[0-9]|2[0-3])-(?:[0-9]|1[0-9]|2[0-3])){0,}/(?:[1-9]|1[0-9]|2[0-3])))s{1,})(?:(L|(?:[0-9]|[1-2][0-9]|3[0-1])W|(?:(?:*|(?:[0-9]|[1-2][0-9]|3[0-1]))(?:/(?:[1-9]|[1-2][0-9]|3[0-1])){0,1})|(?:(?:[0-9]|[1-2][0-9]|3[0-1])(?:-(?:[0-9]|[1-2][0-9]|3[0-1])){0,1}(?:,(?:(?:[0-9]|[1-2][0-9]|3[0-1])(?:-(?:[0-9]|[1-2][0-9]|3[0-1])){0,1})){0,})|(?:(?:[0-9]|[1-2][0-9]|3[0-1])-(?:[0-9]|[1-2][0-9]|3[0-1])(?:,(?:[0-9]|[1-2][0-9]|3[0-1])-(?:[0-9]|[1-2][0-9]|3[0-1])){0,}/(?:[1-9]|[1-2][0-9]|3[0-1])))s{1,})(?:((?:(?:*|[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:/(?:[1-9]|1[0-2])){0,1})|(?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,1}(?:,(?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,1})){0,})|(?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:,(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,}/(?:[1-9]|1[0-2])))s{1,})(?:((?:(?:*|[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:/[1-6]){0,1})|(?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,1}(?:,(?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,1})){0,})|(?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:,(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,}/[1-6]))s{0,})(?:(?|(?:(?:*|d{4})(?:/d{1,4}){0,1})|(?:d{4}(?:-d{4}){0,1}(?:,(?:d{4}(?:-d{4}){0,1})){0,})|(?:d{4}-d{4}(?:,d{4}-d{4}){0,}/d{1,4}))){0,1}s*$
含命令部分
- 非捕获组写法: ^(?:(?:(?:(?:*|[0-5]{0,1}[0-9]{1})(?:/(?:[1-9]|[1-5][0-9])){0,1})|(?:[0-5]{0,1}[0-9]{1}(?:-[0-5]{0,1}[0-9]{1}){0,1}(?:,(?:[0-5]{0,1}[0-9]{1}(?:-[0-5]{0,1}[0-9]{1}){0,1})){0,})|(?:[0-5]{0,1}[0-9]{1}-[0-5]{0,1}[0-9]{1}(?:,[0-5]{0,1}[0-9]{1}-[0-5]{0,1}[0-9]{1}){0,}/(?:[1-9]|[1-5][0-9])))s{1,})(?:(?:(?:(?:*|[0-5]{0,1}[0-9]{1})(?:/(?:[1-9]|[1-5][0-9])){0,1})|(?:[0-5]{0,1}[0-9]{1}(?:-[0-5]{0,1}[0-9]{1}){0,1}(?:,(?:[0-5]{0,1}[0-9]{1}(?:-[0-5]{0,1}[0-9]{1}){0,1})){0,})|(?:[0-5]{0,1}[0-9]{1}-[0-5]{0,1}[0-9]{1}(?:,[0-5]{0,1}[0-9]{1}-[0-5]{0,1}[0-9]{1}){0,}/(?:[1-9]|[1-5][0-9])))s{1,})(?:(?:(?:(?:*|[0-9]|1[0-9]|2[0-3])(?:/(?:[1-9]|1[0-9]|2[0-3])){0,1})|(?:(?:[0-9]|1[0-9]|2[0-3])(?:-(?:[0-9]|1[0-9]|2[0-3])){0,1}(?:,(?:(?:[0-9]|1[0-9]|2[0-3])(?:-(?:[0-9]|1[0-9]|2[0-3])){0,1})){0,})|(?:(?:[0-9]|1[0-9]|2[0-3])-(?:[0-9]|1[0-9]|2[0-3])(?:,(?:[0-9]|1[0-9]|2[0-3])-(?:[0-9]|1[0-9]|2[0-3])){0,}/(?:[1-9]|1[0-9]|2[0-3])))s{1,})(?:(?:L|(?:[0-9]|[1-2][0-9]|3[0-1])W|(?:(?:*|(?:[0-9]|[1-2][0-9]|3[0-1]))(?:/(?:[1-9]|[1-2][0-9]|3[0-1])){0,1})|(?:(?:[0-9]|[1-2][0-9]|3[0-1])(?:-(?:[0-9]|[1-2][0-9]|3[0-1])){0,1}(?:,(?:(?:[0-9]|[1-2][0-9]|3[0-1])(?:-(?:[0-9]|[1-2][0-9]|3[0-1])){0,1})){0,})|(?:(?:[0-9]|[1-2][0-9]|3[0-1])-(?:[0-9]|[1-2][0-9]|3[0-1])(?:,(?:[0-9]|[1-2][0-9]|3[0-1])-(?:[0-9]|[1-2][0-9]|3[0-1])){0,}/(?:[1-9]|[1-2][0-9]|3[0-1])))s{1,})(?:(?:(?:(?:*|[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:/(?:[1-9]|1[0-2])){0,1})|(?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,1}(?:,(?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,1})){0,})|(?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:,(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,}/(?:[1-9]|1[0-2])))s{1,})(?:(?:(?:(?:*|[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:/[1-6]){0,1})|(?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,1}(?:,(?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,1})){0,})|(?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:,(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,}/[1-6]))s{1,})(?:(?:?|(?:(?:*|d{4})(?:/d{1,4}){0,1})|(?:d{4}(?:-d{4}){0,1}(?:,(?:d{4}(?:-d{4}){0,1})){0,})|(?:d{4}-d{4}(?:,d{4}-d{4}){0,}/d{1,4}))s{1}){0,1}(.+)$
- 捕获组写法: ^(?:((?:(?:*|[0-5]{0,1}[0-9]{1})(?:/(?:[1-9]|[1-5][0-9])){0,1})|(?:[0-5]{0,1}[0-9]{1}(?:-[0-5]{0,1}[0-9]{1}){0,1}(?:,(?:[0-5]{0,1}[0-9]{1}(?:-[0-5]{0,1}[0-9]{1}){0,1})){0,})|(?:[0-5]{0,1}[0-9]{1}-[0-5]{0,1}[0-9]{1}(?:,[0-5]{0,1}[0-9]{1}-[0-5]{0,1}[0-9]{1}){0,}/(?:[1-9]|[1-5][0-9])))s{1,})(?:((?:(?:*|[0-5]{0,1}[0-9]{1})(?:/(?:[1-9]|[1-5][0-9])){0,1})|(?:[0-5]{0,1}[0-9]{1}(?:-[0-5]{0,1}[0-9]{1}){0,1}(?:,(?:[0-5]{0,1}[0-9]{1}(?:-[0-5]{0,1}[0-9]{1}){0,1})){0,})|(?:[0-5]{0,1}[0-9]{1}-[0-5]{0,1}[0-9]{1}(?:,[0-5]{0,1}[0-9]{1}-[0-5]{0,1}[0-9]{1}){0,}/(?:[1-9]|[1-5][0-9])))s{1,})(?:((?:(?:*|[0-9]|1[0-9]|2[0-3])(?:/(?:[1-9]|1[0-9]|2[0-3])){0,1})|(?:(?:[0-9]|1[0-9]|2[0-3])(?:-(?:[0-9]|1[0-9]|2[0-3])){0,1}(?:,(?:(?:[0-9]|1[0-9]|2[0-3])(?:-(?:[0-9]|1[0-9]|2[0-3])){0,1})){0,})|(?:(?:[0-9]|1[0-9]|2[0-3])-(?:[0-9]|1[0-9]|2[0-3])(?:,(?:[0-9]|1[0-9]|2[0-3])-(?:[0-9]|1[0-9]|2[0-3])){0,}/(?:[1-9]|1[0-9]|2[0-3])))s{1,})(?:(L|(?:[0-9]|[1-2][0-9]|3[0-1])W|(?:(?:*|(?:[0-9]|[1-2][0-9]|3[0-1]))(?:/(?:[1-9]|[1-2][0-9]|3[0-1])){0,1})|(?:(?:[0-9]|[1-2][0-9]|3[0-1])(?:-(?:[0-9]|[1-2][0-9]|3[0-1])){0,1}(?:,(?:(?:[0-9]|[1-2][0-9]|3[0-1])(?:-(?:[0-9]|[1-2][0-9]|3[0-1])){0,1})){0,})|(?:(?:[0-9]|[1-2][0-9]|3[0-1])-(?:[0-9]|[1-2][0-9]|3[0-1])(?:,(?:[0-9]|[1-2][0-9]|3[0-1])-(?:[0-9]|[1-2][0-9]|3[0-1])){0,}/(?:[1-9]|[1-2][0-9]|3[0-1])))s{1,})(?:((?:(?:*|[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:/(?:[1-9]|1[0-2])){0,1})|(?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,1}(?:,(?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,1})){0,})|(?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:,(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,}/(?:[1-9]|1[0-2])))s{1,})(?:((?:(?:*|[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:/[1-6]){0,1})|(?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,1}(?:,(?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,1})){0,})|(?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:,(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,}/[1-6]))s{1,})(?:(?|(?:(?:*|d{4})(?:/d{1,4}){0,1})|(?:d{4}(?:-d{4}){0,1}(?:,(?:d{4}(?:-d{4}){0,1})){0,})|(?:d{4}-d{4}(?:,d{4}-d{4}){0,}/d{1,4}))s{1}){0,1}(.+)$
五. Java校验Crond表达式
// 非捕获组
String pattern = "^"
// 秒
+ "(?:(?:(?:(?:\*|[0-5]{0,1}[0-9]{1})(?:/(?:[1-9]|[1-5][0-9])){0,1})|(?:[0-5]{0,1}[0-9]{1}(?:\-[0-5]{0,1}[0-9]{1}){0,1}(?:,(?:[0-5]{0,1}[0-9]{1}(?:\-[0-5]{0,1}[0-9]{1}){0,1})){0,})|(?:[0-5]{0,1}[0-9]{1}\-[0-5]{0,1}[0-9]{1}(?:,[0-5]{0,1}[0-9]{1}\-[0-5]{0,1}[0-9]{1}){0,}/(?:[1-9]|[1-5][0-9])))\s{1,})"
// 分
+ "(?:(?:(?:(?:\*|[0-5]{0,1}[0-9]{1})(?:/(?:[1-9]|[1-5][0-9])){0,1})|(?:[0-5]{0,1}[0-9]{1}(?:\-[0-5]{0,1}[0-9]{1}){0,1}(?:,(?:[0-5]{0,1}[0-9]{1}(?:\-[0-5]{0,1}[0-9]{1}){0,1})){0,})|(?:[0-5]{0,1}[0-9]{1}\-[0-5]{0,1}[0-9]{1}(?:,[0-5]{0,1}[0-9]{1}\-[0-5]{0,1}[0-9]{1}){0,}/(?:[1-9]|[1-5][0-9])))\s{1,})"
// 时
+ "(?:(?:(?:(?:\*|[0-9]|1[0-9]|2[0-3])(?:/(?:[1-9]|1[0-9]|2[0-3])){0,1})|(?:(?:[0-9]|1[0-9]|2[0-3])(?:\-(?:[0-9]|1[0-9]|2[0-3])){0,1}(?:,(?:(?:[0-9]|1[0-9]|2[0-3])(?:\-(?:[0-9]|1[0-9]|2[0-3])){0,1})){0,})|(?:(?:[0-9]|1[0-9]|2[0-3])\-(?:[0-9]|1[0-9]|2[0-3])(?:,(?:[0-9]|1[0-9]|2[0-3])\-(?:[0-9]|1[0-9]|2[0-3])){0,}/(?:[1-9]|1[0-9]|2[0-3])))\s{1,})"
// 日
+ "(?:(?:L|(?:[0-9]|[1-2][0-9]|3[0-1])W|(?:(?:\*|(?:[0-9]|[1-2][0-9]|3[0-1]))(?:/(?:[1-9]|[1-2][0-9]|3[0-1])){0,1})|(?:(?:[0-9]|[1-2][0-9]|3[0-1])(?:\-(?:[0-9]|[1-2][0-9]|3[0-1])){0,1}(?:,(?:(?:[0-9]|[1-2][0-9]|3[0-1])(?:\-(?:[0-9]|[1-2][0-9]|3[0-1])){0,1})){0,})|(?:(?:[0-9]|[1-2][0-9]|3[0-1])\-(?:[0-9]|[1-2][0-9]|3[0-1])(?:,(?:[0-9]|[1-2][0-9]|3[0-1])\-(?:[0-9]|[1-2][0-9]|3[0-1])){0,}/(?:[1-9]|[1-2][0-9]|3[0-1])))\s{1,})"
// 月
+ "(?:(?:(?:(?:\*|[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:/(?:[1-9]|1[0-2])){0,1})|(?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:\-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,1}(?:,(?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:\-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,1})){0,})|(?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)\-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:,(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)\-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,}/(?:[1-9]|1[0-2])))\s{1,})"
// 周
+ "(?:(?:(?:(?:\*|[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:/[1-6]){0,1})|(?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:\-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,1}(?:,(?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:\-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,1})){0,})|(?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)\-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:,(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)\-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,}/[1-6]))\s{1,})"
// 年
+ "(?:(?:\?|(?:(?:\*|\d{4})(?:/\d{1,4}){0,1})|(?:\d{4}(?:\-\d{4}){0,1}(?:,(?:\d{4}(?:\-\d{4}){0,1})){0,})|(?:\d{4}\-\d{4}(?:,\d{4}\-\d{4}){0,}/\d{1,4}))\s{1}){0,1}"
// 指令
+ "(.+)"
+ "$";
String test01 = "1-10,20-30/2 1,5,15,59 1-6/2 * JAN-DEC/2 *";
System.out.println(Pattern.matches(pattern, test01));
// 输出 false
String test02 = "1-10,20-30/2 1,5,15,59 1-6/2 * JAN-DEC/2 * ?";
System.out.println(Pattern.matches(pattern, test02));
// 输出 true, 其中 '?' 被识别为指令
String test03 = "1-10,20-30/2 1,5,15,59 1-6/2 * JAN-DEC/2 * ? ";
System.out.println(Pattern.matches(pattern, test03));
// 输出 true, 其中 '? ' 被识别为指令
String test04 = "1-10,20-30/2 1,5,15,59 1-6/2 * JAN-DEC/2 * ? ";
System.out.println(Pattern.matches(pattern, test04));
// 输出 true, 其中 ' ' 被识别为指令, 空指令可以被执行
String test05 = "1-10,20-30/2 1,5,15,59 1-6/2 * JAN-DEC/2 * ? echo 3 > /proc/sys/vm/drop_caches";
System.out.println(Pattern.matches(pattern, test05));
// 输出 true
// 捕获组
pattern = "^"
// 秒
+ "(?:((?:(?:\*|[0-5]{0,1}[0-9]{1})(?:/(?:[1-9]|[1-5][0-9])){0,1})|(?:[0-5]{0,1}[0-9]{1}(?:\-[0-5]{0,1}[0-9]{1}){0,1}(?:,(?:[0-5]{0,1}[0-9]{1}(?:\-[0-5]{0,1}[0-9]{1}){0,1})){0,})|(?:[0-5]{0,1}[0-9]{1}\-[0-5]{0,1}[0-9]{1}(?:,[0-5]{0,1}[0-9]{1}\-[0-5]{0,1}[0-9]{1}){0,}/(?:[1-9]|[1-5][0-9])))\s{1,})"
// 分
+ "(?:((?:(?:\*|[0-5]{0,1}[0-9]{1})(?:/(?:[1-9]|[1-5][0-9])){0,1})|(?:[0-5]{0,1}[0-9]{1}(?:\-[0-5]{0,1}[0-9]{1}){0,1}(?:,(?:[0-5]{0,1}[0-9]{1}(?:\-[0-5]{0,1}[0-9]{1}){0,1})){0,})|(?:[0-5]{0,1}[0-9]{1}\-[0-5]{0,1}[0-9]{1}(?:,[0-5]{0,1}[0-9]{1}\-[0-5]{0,1}[0-9]{1}){0,}/(?:[1-9]|[1-5][0-9])))\s{1,})"
// 时
+ "(?:((?:(?:\*|[0-9]|1[0-9]|2[0-3])(?:/(?:[1-9]|1[0-9]|2[0-3])){0,1})|(?:(?:[0-9]|1[0-9]|2[0-3])(?:\-(?:[0-9]|1[0-9]|2[0-3])){0,1}(?:,(?:(?:[0-9]|1[0-9]|2[0-3])(?:\-(?:[0-9]|1[0-9]|2[0-3])){0,1})){0,})|(?:(?:[0-9]|1[0-9]|2[0-3])\-(?:[0-9]|1[0-9]|2[0-3])(?:,(?:[0-9]|1[0-9]|2[0-3])\-(?:[0-9]|1[0-9]|2[0-3])){0,}/(?:[1-9]|1[0-9]|2[0-3])))\s{1,})"
// 日
+ "(?:(L|(?:[0-9]|[1-2][0-9]|3[0-1])W|(?:(?:\*|(?:[0-9]|[1-2][0-9]|3[0-1]))(?:/(?:[1-9]|[1-2][0-9]|3[0-1])){0,1})|(?:(?:[0-9]|[1-2][0-9]|3[0-1])(?:\-(?:[0-9]|[1-2][0-9]|3[0-1])){0,1}(?:,(?:(?:[0-9]|[1-2][0-9]|3[0-1])(?:\-(?:[0-9]|[1-2][0-9]|3[0-1])){0,1})){0,})|(?:(?:[0-9]|[1-2][0-9]|3[0-1])\-(?:[0-9]|[1-2][0-9]|3[0-1])(?:,(?:[0-9]|[1-2][0-9]|3[0-1])\-(?:[0-9]|[1-2][0-9]|3[0-1])){0,}/(?:[1-9]|[1-2][0-9]|3[0-1])))\s{1,})"
// 月
+ "(?:((?:(?:\*|[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:/(?:[1-9]|1[0-2])){0,1})|(?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:\-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,1}(?:,(?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:\-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,1})){0,})|(?:(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)\-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:,(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)\-(?:[0-9]|1[0-2]|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,}/(?:[1-9]|1[0-2])))\s{1,})"
// 周
+ "(?:((?:(?:\*|[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:/[1-6]){0,1})|(?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:\-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,1}(?:,(?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:\-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,1})){0,})|(?:(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)\-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)(?:,(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)\-(?:[0-7]|SUN|MON|TUE|WED|THU|FRI|SAT)){0,}/[1-6]))\s{1,})"
// 年
+ "(?:(\?|(?:(?:\*|\d{4})(?:/\d{1,4}){0,1})|(?:\d{4}(?:\-\d{4}){0,1}(?:,(?:\d{4}(?:\-\d{4}){0,1})){0,})|(?:\d{4}\-\d{4}(?:,\d{4}\-\d{4}){0,}/\d{1,4}))\s{1}){0,1}"
// 指令
+ "(.+)" + "$";
Matcher m = Pattern.compile(pattern).matcher(test05);
if (m.find()) {
System.out.println("Found value: '" + m.group(0) + "'");
System.out.println("Found value: '" + m.group(1) + "'");
System.out.println("Found value: '" + m.group(2) + "'");
System.out.println("Found value: '" + m.group(3) + "'");
System.out.println("Found value: '" + m.group(4) + "'");
System.out.println("Found value: '" + m.group(5) + "'");
System.out.println("Found value: '" + m.group(6) + "'");
System.out.println("Found value: '" + m.group(7) + "'");
System.out.println("Found value: '" + m.group(8) + "'");]
}
// 输出
请多多指教
不含命令部分
含命令部分



