RegEx для сопоставления конкретных номеров телефонов - PullRequest
4 голосов
/ 20 мая 2019

Я пытаюсь проверить, соответствует ли строка формату номера телефона моей страны, который является кодом города (две цифры, которые могут или не могут предшествовать 0, а также могут быть в скобках), за которыми следуют 8 или 9 цифр в котором перед 4 последними цифрами может быть символ тире. Вот некоторые допустимые форматы:


'00 00000000'
'000-000000000'
'000 00000-0000'
'00 0000-0000'
'(00) 0000-0000'
'(000) 000000000'

Пока это рабочее выражение, которое у меня есть:


p = /0?\d{2}\s?-?\s?\d{4,5}\s?-?\s?\d{4}/

Я попытался использовать условное выражение, чтобы проверить, находится ли код города в круглых скобках с /?(\() 0?\d{2}\)|0?\d{2} \s?-?\s?\d{4,5}\s?-?\s?\d{4}/, но получил ошибку (repl):1: target of repeat operator is not specified: /?(\() 0?\d{2}\)|0?\d{2} \s?-?\s?\d{4,5}\s?-?\s?\d{4}.

Что я здесь не так делаю?

Ответы [ 5 ]

4 голосов
/ 20 мая 2019

Мой ответ обращается к вашей условной идее для необязательных скобок.
Ruby поддерживает условные версии начиная с версии 2.0. Синтаксис равен (?(A)X|Y): если A истинно, X еще Y.

  • Положите необязательный группа захвата , содержащая открывающую скобку в начале:
    ^(\()?
  • Позже где-нибудь в шаблоне проверьте, удалось ли это:
    (?(1)\) |[ -])
    В случае успеха: требуется закрытие ) с последующим пробелом | остальное: [ -] пробел или тире.

Таким образом, весь шаблон с условным условием может быть

^(\()?0?\d{2}(?(1)\) |[ -])\d{4,5}[ -]?\d{4}$

См. Демонстрацию на Rubular или Regex101 . Отрегулируйте дальше под свои нужды.

Альтернатива использованию чередования (?:\(abc\)|abc), на которую @CarySwoveland уже ответил, но ответ @ AlekseiMatiushkin, несомненно, облегчит мне жизнь.

4 голосов
/ 20 мая 2019

Не проверяйте номера телефонов с помощью регулярных выражений. Могу поспорить, что вы не хотите исключать те, которые иногда вводят 2 последовательных пробела или что-то в этом роде.

Вместо этого отфильтруйте все нецифровые и начальные нули, а затем подтвердите. Как это:

number.gsub(/\D+/, '').gsub(/\A0+/) =~ /\d{8,9}/

Я не уверен, что это будет соответствовать вашим потребностям из коробки, но держу пари, что вы поняли. В конце концов, [000]1234 56789 - понятный номер телефона.

2 голосов
/ 20 мая 2019

Полагаю, вы можете использовать следующее регулярное выражение.

R = /
    \A            # match beginning of string
    (?:           # begin a non-capture group
      \(0?\d{2}\) # match '(' then an optional `0` then two digits then ')'
    |             # or
      0?\d{2}     # match an optional `0` then two digits
    )             # end the non-capture group
    (?:           # begin a non-capture group
      [ ]+        # match one or more spaces
    |             # or
      -           # match a hyphen
    )             # end the non-capture group
    \d{4,5}       # match 4 or 5 digits
    -?            # optionally match a hyphen
    \d{4}         # match 4 digits
    \z            # match end of string
    /x            # free-spacing regex definition mode

arr = [
  '00 00000000',
  '000-000000000',
  '000 00000-0000',
  '00 0000-0000',
  '(00) 0000-0000',
  '(000) 000000000',
  '(000 000000000',
  '(0000) 000000000'
]

arr.map { |s| s.match? R }
  #=> [true, true, true, true, true, true, false, false]

Регулярное выражение обычно записывается следующим образом.

R = /\A(?:\(0?\d{2}\)|0?\d{2})(?: +|-)\d{4,5}-?\d{4}\z/

Это следует изменить следующим образом, если начальные цифры не могут быть равны нулю.(Если, например, '001-123456789' и '(12)-023456789' недействительны.)

R = /\A(?:\(0?[1-9]\d\)|0?\[1-9]\d)(?: +|-)[1-9]\d{3,4}-?\d{4}\z/
2 голосов
/ 20 мая 2019

Может быть несколько способов проверить эти числа.Одним из способов будет то, что мы напишем все наши возможные номера телефонов, а затем напишем выражение для него.Возможно, аналогично:

[0-9]{2,3}(\s|-)[0-9]{4,5}-?[0-9]{3,4}

Тест

re = /[0-9]{2,3}(\s|-)[0-9]{4,5}-?[0-9]{3,4}/m
str = '\'00 00000000\'
\'000-000000000\'
\'000 00000-0000\'
\'00 0000-0000\''

# Print the match result
str.scan(re) do |match|
    puts match.to_s
end

Демо

Этот фрагмент кода просто показывает группы захвата и то, что выражение может быть допустимым:

const regex = /[0-9]{2,3}(\s|-)[0-9]{4,5}-?[0-9]{3,4}/gm;
const str = `'00 00000000'
'000-000000000'
'000 00000-0000'
'00 0000-0000'`;
let m;

while ((m = regex.exec(str)) !== null) {
    // This is necessary to avoid infinite loops with zero-width matches
    if (m.index === regex.lastIndex) {
        regex.lastIndex++;
    }
    
    // The result can be accessed through the `m`-variable.
    m.forEach((match, groupIndex) => {
        console.log(`Found match, group ${groupIndex}: ${match}`);
    });
}

RegEx

Если это выражение нежелательно, его можно изменить или изменить в regex101.com .

enter image description here

RegEx Circuit

jex.im также помогает визуализировать выражения.

enter image description here


Редактировать 1:

В случае () мы хотим добавить два отрицательных взгляда позади нашего начальноговыражение.Может быть, похоже на это :

\(?[0-9]{2,3}\)?(\s|-)[0-9]{4,5}-?[0-9]{3,4}

enter image description here

0 голосов
/ 21 мая 2019

Не делайте этого, если только вы не знаете, что работаете в очень, очень ограниченной области, например,

  • Номера передаются в систему, которая принимает только определенныеформат, чтобы вы знали, что эти точные форматы и никакие другие не будут работать
  • Числа просто читаются человеком, так что вы можете позволить им разобраться в этом и не нужно ничего проверять

В противном случае вам следует использовать надежную библиотеку, такую ​​как https://github.com/mobi/telephone_number (по мотивам libphonenumber от Google )

...