正则表达太僵硬了

时间:2017-11-01 18:37:40

标签: php regex

我使用以下正则表达式来查找字符串中的电话:

([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})

它适用于以下数字:

555-555-5555 (555)555-5555 (555) 555-5555

但是,如果字符串中有额外的空格,则找不到手机。    555 -555-5555 (555)555- 5555 (555) 555 -5555

是否可以修改以允许一两个空格?我的输入来自OCR,而不是用户输入,因此我不需要格式化输入。

感谢。

4 个答案:

答案 0 :(得分:1)

根据您的示例,您可以使用

[(\d](?:(?!\h{2,})[-\d()\h])*\d

a demo on regex101.com

<小时/> 那是

[(\d]          # one of ( or 0-9
(?:            # a non-capturing group
    (?!\h{2,}) # make sure not 2+ horizontal whitespaces are immediately ahead
    [-\d()\h]  # then match one of -, 0-9, () or whitespaces
)*             # zero or more times
\d             # the end must be a digit

这是the tempered greedy token的变体。

<小时/> 在PHP中,这可能是

<?php
$data = <<<DATA
555-555-5555   (555)555-5555    (555) 555-5555

However, if there\'s an extra space inside the string it does not find the phone. 555 -555-5555   (555)555- 5555    (555) 555 -5555
DATA;

$regex = '~[(\d](?:(?!\h{2,})[-\d()\h])*\d~';

preg_match_all($regex, $data, $matches);
print_r($matches);
?>

哪个收益

Array
(
    [0] => Array
        (
            [0] => 555-555-5555
            [1] => (555)555-5555
            [2] => (555) 555-5555
            [3] => 555 -555-5555
            [4] => (555)555- 5555
            [5] => (555) 555 -5555
        )

)

答案 1 :(得分:0)

如果我理解,您只想使用正则表达式,那么您可以在每个模式组中添加\s*,例如

([0-9]{3})\)?\s*[-. ]?\s*([0-9]{3})\s*[-. ]?\s*([0-9]{4})\s*

这是基于您的请求脚本

Here a DEMO EXAMPLE

答案 2 :(得分:0)

我觉得你要求的是一种非常宽松/包容的模式。

这个很宽容:/\(?\d{3}\)? {0,2}[-.]? {0,2}\d{3} {0,2}[-.]? {0,2}\d{4}/

Pattern Demo Link

它将匹配所有这些变体(......和更多):

555-555-5555
(555)555-5555
(555) 555-5555
555 -555-5555
(555)555- 5555
(555) 555 -5555
555.555-5555
555.555.5555
5555555555
555-555.5555
(555)5555555
(555).555.5555
(555)-555-5555
(555555-5555
555)-555-5555
555555-5555
555 5555555
555 555 5555
555 - 555 - 5555
555555  .  5555

模式逻辑按此顺序:

  • 允许选择(
  • 需要3位数
  • 允许选择)
  • 允许零个,一个或两个文字空间
  • 允许使用可选的连字符或点
  • 允许零个,一个或两个文字空间
  • 需要3位数
  • 允许零个,一个或两个文字空间
  • 允许使用可选的连字符或点
  • 允许零个,一个或两个文字空间
  • 需要4位数

答案 3 :(得分:0)

要限制添加的空格数,您可以检查最后一组的第一个数字的位置(您也可以选择最后一个数字)。然后你要做的就是按照你想要的方式描述不同的分隔符。

~[(\d](?:\b\d{3}\)(?=.{3,5}\W\b) {0,2}\d{3}|\B\d{2}(?=.{4,6}\W\b)(?:- ?| -? ?)\d{3})(?:- ?| -? ?)\d{4}\b~

demo

更具可读性的相同模式:

~
[(\d]  # first character discrimination technic (avoid the cost of an alternation
       # at the start of the pattern)
(?: # with brackets
    \b \d{3} \)
    (?= .{3,5} \W \b )
    \g<spb> \d{3}
  | # without brackets
    \B \d{2} # you can also replace \B with (?<=\b\d) to check the word-boundary
    (?= .{4,6} \W \b )
    \g<sp> \d{3}
)
\g<sp> \d{4} \b

# subpattern definitions:
(?<spb> [ ]{0,2} ){0}             # separator after bracket
(?<sp> - [ ]? | [ ] -? [ ]? ){0}  # other separators
~x

demo

随意将-更改为[.-]或定义您自己允许的分隔符。在这种情况下,不要忘记更改前瞻中的量词。此外,如果要允许第二个分隔符为空,请检查最后一个数字后的边界,而不是最后一个组的第一个数字之前的边界。