2020-05-16 5 kyu validDate Regex
2020-05-17 本文已影响0人
苦庭
My answer / AC
var validDate = /(?<=\[)((0[13578]\-(0[1-9]|[1-2][0-9]|3[01]))|(1[02]\-(0[1-9]|[1-2][0-9]|3[01]))|(0[469]\-(0[1-9]|[1-2][0-9]|30))|(11\-(0[1-9]|[1-2][0-9]|30))|(02\-(0[1-9]|1[0-9]|2[0-8])))(?=\])/;
哪里不好?
- 为了使用或
|
大量编组了,实际上会占据不少的内存。优化=将分组变为非捕捉分组,即(expr)
->(?:expr)
- 31天月份里的10、12月是可以合并到前面的13578月里面的,只要加多一个组,中间加个
|
即可。30天月份类似。
Best answer
var days28 = /02-(0[1-9]|1\d|2[0-8])/
var days30 = /(?:0[469]|11)-(?:0[1-9]|[12]\d|30)/
var days31 = /(?:0[13578]|10|12)-(?:0[1-9]|[12]\d|3[01])/
var validDate = new RegExp(
'\\[(' +
'(?:' + days28.source + ')|' +
'(?:' + days30.source + ')|' +
'(?:' + days31.source + ')' +
')\\]'
)
好在哪里?
- 分组清晰一目了然
- 多用非捕捉分组
- 小知识:正则字面量这个对象只要取它的source属性,就能够得到它的正则字符串表达式。
Best answer2
const validDate = /\[(?!(0[2469]|11)-31)(?!02-(29|30))(0[1-9]|1[0-2])-(?!00)([0-2]\d|3[01])\]/;
这个是另外一个我觉得很聪明的写法,能够将非捕捉分组的“AND”特性运用起来。
-
(?:expr)
的意思是:对expr进行匹配,匹配完了,匹配到了(否则当前正则匹配判定为失败,移向下一个匹配点),之后在原来的匹配点接着匹配。"match expr but after that continue matching at the original match-point." - 那么
(?!expr)
的意思是:对expr进行匹配,匹配完了,匹配不到,之后在原来的匹配点接着匹配。
因此在这个回答中,非捕获分组(?!(0[2469]|11)-31)(?!02-(29|30))
不能满足的话才能继续接着匹配,从而达到判断排除不符合天数的月份的目的。