快速拍摄,自由间距,可能远非高效(首先因为单个范围会使正则表达式回溯,当它发现它后面没有“|”时) - 请参阅下面的版本 2,这是(我相信)效率更高:
^ # Start of string
(?: # Start group, non-capturing
[([] # '(' or '['
\s* # optional whitespace
[0-9]+ # at least one digit 0-9
(?:\.[0-9]+)? # optionally '.' followed by at least one digit 0-9
\s* # optional whitespace
, # ','
\s* # optional whitespace
[0-9]+ # at least one digit 0-9
(?:\.[0-9]+)? # optionally '.' followed by at least one digit 0-9
\s* # optional whitespace
[)\]] # ')' or ']'
\s* # optional whitespace
\| # '|'
\s* # optional whitespace
)* # all the above may appear 0 or more times
[([] # The remainder is exactly the same as the group above,
\s* # used for a single range or the last range -
[0-9]+ # i.e., a range NOT followed by '|' - of a multi range.
(?:\.[0-9]+)?
\s*
,
\s*
[0-9]+
(?:\.[0-9]+)?
\s*
[)\]]
$ # end of string
这将匹配例如:
[1.5, 3]
[23.7, 3.70)
[2.9 , 3]|[3,2)
[1.5, 4] | [6.9, 9.3) | [10, 11]
(1.5, 3]
[23.7, 3.70)
(1.5, 5.0)
但不是:
[23.7, 3.70) | (7, 9) | // trailing OR
| [23.7, 3.7] // leading OR
请注意,它不能确保第二个数字实际上高于第一个。为此,我真的建议将其留给 /a 解析器 - 或添加捕获组并在正则表达式之外处理它们。
版本 2
由于更少的回溯,这应该更有效 - 它基本上是从:
(任意数量的范围后跟|)后跟一个范围
... 至:
后跟的范围(任意数量的以 | 开头的范围)
ETA:解释一下,版本 1 开始检查“后跟 | 的范围”。
如果我们只有一个范围,那就是浪费时间。当它到达“|” 它将重新开始,检查正则表达式的第二部分 - 即是否存在所需的“没有|的范围”?
相反,在版本 2 中,我们开始检查简单的“范围”。这意味着,如果只有一个范围,它将成功而无需任何回溯。如果我们给它乱码,例如hello
,它会立即失败,因为它现在知道第一个字符必须是 a(
或[
- 它不是可选的。而在版本 1 中,因为第一部分是可选的,所以它必须检查正则表达式的第二部分以确保它也失败了。
在几乎所有其他情况下(我已经测试过),版本 2 匹配 - 或不匹配 - 只需更少的步骤。
在这里,由于它基本上是相同的正则表达式,但某些部分已切换,因此我将在评论中放置一个示例匹配:
^
[([] # (
\s* #
[0-9]+ # 3
(?:\.[0-9]+)? # .90
\s* #
, # ,
\s* #
[0-9]+ # 43
(?:\.[0-9]+)? # .2
\s* #
[)\]] # ]
#
(?: #
\s* #
\| # |
\s* #
#
[([] # [
\s* #
[0-9]+ # 55
(?:\.[0-9]+)? # .20
\s* #
, # ,
\s* #
[0-9]+ # 2
(?:\.[0-9]+)? # .91
\s* #
[)\]] # )
)*
$
匹配和不匹配应与版本 1 相同。