[编辑:发布后,我发现它与@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 也应该被允许。这是上述的一个小变体,我们不必费心创建另一个正则表达式来包含在联合中;相反,我们只是修改r2ever-so-slightly:
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
看来,当数字以+ 开头时,+ 必须后跟两位数字、一个空格、一位数字、一个空格,然后是四对以空格分隔的数字。我们可以把它写下来:
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,然后手动调整它。