问题
I am trying to validate birthdays using the following regex:
^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[1,3-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$
This regex works when tested in an online regex tester, but when I try to use this regex inside my firebase rules, Firebase seems to not accept it. I also tried doubling my backslashes and still no luck.
This is my firebase rule:
".validate": "newData.isString() && newData.val().matches(/^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[1,3-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$/)"
This is the error I get on Firebase: "Illegal regular expression, unescaped ^, ^ can only appear at the end of regular expressions"
How can I tweak this regex to get it working on Firebase?
回答1:
You need to do two things here:
- make sure all backslashes are doubled
- turn all non-capturing groups into capturing ones and re-adjust the backreferences (note that redundant capturing groups should be eliminated) (note you can't use
\15
as backreference, it seems only 1 to 9 backreferences are supported) - re-vamp the pattern so that the
^
start of string anchor appeared at the beginning and$
only at the end of the regular expression (otherwise, you will get the illegal regex exception). It is easy to do here as your pattern is of the^a1$|^a2$|^a3$
type, and it is equal to^(?:a1|a2|a3)$
.
The pattern should look like
newData.val().matches(/^((31([-\\/.])(0?[13578]|1[02])\\3|(29|30)([-\\/.])(0?[13-9]|1[0-2])\\6)(1[6-9]|[2-9]\\d)?\\d{2}|29([-\\/.])0?2\\9((1[6-9]|[2-9]\\d)?(0[48]|[2468][048]|[13579][26])|(16|[2468][048]|[3579][26])00)|(0?[1-9]|1\\d|2[0-8])([-\\/.])(0?[1-9]|1[0-2])[-\\/.](1[6-9]|[2-9]\\d)?\\d{2})$/)
Note that I also turned (\/|-|\.)
into ([-\/.])
(since a character class is more efficient than plain alternation with single-char alternatives) and remove a comma from [1,3-9]
- it looks like a typo, you wanted to match 1
or a digit from 3
to 9
, I believe, and a ,
is treated literally in a character class.
来源:https://stackoverflow.com/questions/50571573/firebase-rules-regex-birthday