[编辑:发布后,我发现它与@Lucas 的答案非常相似。但是,我将让它代表另一种演示文稿。]
我会尝试为每个允许的模式构建一个正则表达式,然后将它们的并集获取一个正则表达式。
我们看到所有不以+
10 位开头的允许数字,所以我假设这是一个要求。如果允许不同的位数,则可以轻松处理。
1.包括0665363636,不包括2336653636和0065363636
我认为这意味着数字必须以数字开头0
,而第二个数字不能是0
。这很容易:
r1 = /
^ # match start of string
0 # match 0
[1-9] # match any digit 1-9
\d{8} # match 8 digits
$ # match end of string
/x
测试:
'0665363636' =~ r1 #=> 0
'2336653636' =~ r1 #=> nil
'0065363636' =~ r1 #=> nil
这似乎行得通。
2. 包括 06 65 36 36 36,不包括 06 65 36 36
另一个简单的:
r2 = /
^ # match start of string
0 # match 0
[1-9] # match any digit 1-9 # or \d if can be zero
(?: # begin a non-capture group
\s # match one whitespace
\d{2} # match two digits
) # end capture group
{4} # match capture group 4 times
$ # match end of string
/x
测试:
'06 65 36 36 36' =~ r2 #=> 0
'06 65 36 36' =~ r2 #=> nil
又一个明显的成功!
我们认为这06-65-36-36-36
也应该被允许。这是上述的一个小变体,我们不必费心创建另一个正则表达式来包含在联合中;相反,我们只是r2
稍微修改一下:
r2 = /^0[1-9](?:
[\s-] # match one whitespace or a hyphen
\d{2}){4}$
/x
请注意,当连字符在字符类中时,我们不必转义它。
测试:
'06 65 36 36 36' =~ r2 #=> 0
'06-65-36-36-36' =~ r2 #=> 0
是的!
3. 包括 +33 6 65 36 36 36,不包括 +3366536361
看来,当数字以 a 开头时+
,+
必须后跟两位数字,一个空格,一位数字,一个空格,然后是四对以空格分隔的数字。我们可以把它写下来:
r3 = /
^ # match start of string
\+ # match +
\d\d # match two digits
\s\d # match one whitespace followed by a digit
(?: # begin a non-capture group
\s # match one whitespace
\d{2} # match two digits
) # end capture group
{4} # match capture group 4 times
$ # match end of string
/x
测试:
'+33 6 65 36 36 36' =~ r3 #=> 0
'+3366536361' =~ r3 #=> nil
搞定了!
联合起来!
r = Regexp.union(r1, r2, r3)
=> /(?x-mi:
^ # match start of string
0 # match 0
[1-9] # match any digit 1-9
\d{8} # match 8 digits
$ # match end of string
)|(?x-mi:^0[1-9](?:
[\s-] # match one whitespace or a hyphen
\d{2}){4}$
)|(?x-mi:
^ # match start of string
\+ # match +
\d\d # match two digits
\s\d # match one whitespace followed by a digit
(?: # begin a non-capture group
\s # match one whitespace
\d{2} # match two digits
) # end capture group
{4} # match capture group 4 times
$ # match end of string
)/
让我们尝试一下:
['0665363636', '06 65 36 36 36', '06-65-36-36-36',
'+33 6 65 36 36 36'].any? { |s| (s =~ r).nil? } #=> false
['06 65 36 36', '2336653636', '+3366536361',
'0065363636'].all? { |s| (s =~ r).nil? } #=> true
答对了!
效率
联合单个正则表达式可能不会产生最有效的单个正则表达式。您必须确定更容易的初始构建和测试以及持续维护的好处是否值得效率损失。如果效率是最重要的,您可能仍然以r
这种方式构建,然后手动调整它。