【问题标题】:regular expression ruby phone number正则表达式 ruby​​ 电话号码
【发布时间】:2015-07-20 07:29:38
【问题描述】:

我正在尝试弄清楚如何编写自己的正则表达式。

我列出了可行的电话号码和不可行的电话号码,并试图确保包括可行的电话号码,但我不知道如何完成。

允许列表

0665363636 //
06 65 36 36 36 //
06-65-36-36-36 //
+33 6 65 36 36 36

不允许

06 65 36 36 //
2336653636 //
+3366536361 //
0065363636 

我有点搞砸了,我现在有这个:

[0+][63][6 \-3][56\ ][\d{1}][\d \-]\d{2}[\d{1} \-]\d\d? ?\-?\d?\d? ?\d?\d?$

这阻止了不允许的 2 号和 4 号,但我似乎无法弄清楚如何阻止其他的。

我应该输入最少数量的数字吗?如果是这样,我该怎么做。

【问题讨论】:

  • 卢卡斯提供了正确答案。另一种方法是使用 gsub 清理传入的电话号码,这样号码中就没有空格或 +。 phone_number.gsub(/[^\d\+]/, "") 然后它可以像这样小:/^(0|\+33)[1-9]\d{8}$/

标签: ruby regex rubular


【解决方案1】:

[编辑:发布后,我发现它与@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,然后手动调整它。

【讨论】:

    【解决方案2】:

    您似乎想将允许的电话号码限制为仅限法国手机号码。

    您列出了有效和无效字符串,这是一个很好的起点。但是,我认为您只想一次性编写模式,这很容易出错。

    让我们遵循一种简单的方法,浏览允许的列表并为每个列表制作一个非常简单的正则表达式:

    0665363636         -> ^06\d{8}$
    06 65 36 36 36     -> ^06(?: \d\d){4}$
    06-65-36-36-36     -> ^06(?:-\d\d){4}$
    +33 6 65 36 36 36  -> ^\+33 6(?: \d\d){4}$
    

    到目前为止一切顺利。

    现在,只需将所有内容组合到一个正则表达式中,并稍微考虑一下(06 部分在前 3 种情况下很常见):

    ^06(?:\d{8}|(?: \d\d){4}|(?:-\d\d){4})|\+33 6(?: \d\d){4}$
    

    等等。 Demo here.


    作为旁注,您应该使用:

    ^0[67](?:\d{8}|(?: \d\d){4}|(?:-\d\d){4})|\+33 [67](?: \d\d){4}$
    

    因为法国的手机号码也可以从 07 开始。

    【讨论】:

    • 谢谢,这清楚地解释了我的思考过程。但是,当我使用我的大学给我的网站时,它列出的好像只接受第四个。他们提供的网站是 rubular.com。编辑;好像rubular在^上坏了
    • @Martijn 这适用于我的 rubular,请参阅 this link,您可能还必须使用 m 选项。
    猜你喜欢
    • 2017-09-23
    • 2014-02-15
    • 2016-02-02
    • 2011-12-14
    • 2013-05-26
    • 1970-01-01
    相关资源
    最近更新 更多