Хорошо, у меня есть это регулярное выражение:
( |^|>)(((((((\+|00)(31|32)( )?(\(0\))?)|0)([0-9]{2})(-)?( )?)?)([0-9]{7}))|((((((\+|00)(31|32)( )?(\(0\))?)|0)([0-9]{3})(-)?( )?)?)([0-9]{6}))|((((((\+|00)(31|32)( )?(\(0\))?)|0)([0-9]{1})(-)?( )?)?)([0-9]{8})))( |$|<)
Он форматирует голландские и бельгийские телефонные номера (мне нужны только те, которые, следовательно, 31 и 32 в качестве кода страны).
Расшифровывать это не так уж и весело, но, как вы можете видеть, в нем также есть много дубликатов. но теперь он справляется с этим очень точно
Принимаются все следующие номера телефонов в европейском формате
0031201234567
0031223234567
0031612345678
+31(0)20-1234567
+31(0)223-234567
+31(0)6-12345678
020-1234567
0223-234567
06-12345678
0201234567
0223234567
0612345678
и следующие ложно отформатированные не
06-1234567 (mobile phone number in the Netherlands should have 8 numbers after 06 )
0223-1234567 (area code with home phone)
в отличие от этого, что хорошо.
020-1234567 (area code with 3 numbers has 7 numbers for the phone as opposed to a 4 number area code which can only have 6 numbers for phone number)
Как видите, это немного затрудняет использование символа «-», но он мне нужен, потому что это часть форматирования, обычно используемого людьми, и я хочу иметь возможность анализировать их все.
Теперь мой вопрос ... видите ли вы способ упростить это регулярное выражение (или даже улучшить его, если вы видите в нем ошибку), сохраняя при этом те же правила?
Вы можете протестировать это на regextester.com
('(| ^ |>)' Предназначен для проверки того, стоит ли он в начале слова, с возможностью того, что ему предшествует новая строка или '>'. Я ищу телефонные номера на страницах HTML.)
нет, я ищу телефонные номера в кучу текстов, я не знаю, где этот номер и как он отформатирован. после того, как я его нашел, мне это больше не нужно





Господи Всевышний, какой бардак! :) Если у вас есть семантические или бизнес-правила высокого уровня (например, те, которые вы описываете, говоря о европейских числах, числах в Нидерландах и т. д.), Вам, вероятно, будет лучше разбить этот единственный тест регулярного выражения на несколько отдельных тестов регулярного выражения, по одному для каждого из ваших правил высокого уровня.
if number =~ /...../ # Dutch mobiles
# ...
elsif number =~ /..../ # Belgian landlines
# ...
# etc.
end
Так будет немного легче читать, поддерживать и изменять.
И упорядочите свои тесты по наиболее вероятному совпадению (при условии, что вы достаточно хорошо знаете демографические данные).
Разделите его на несколько выражений. Например (псевдокод) ...
phone_no_patterns = [
/[0-9]{13}/, # 0031201234567
/+(31|32)\(0\)\d{2}-\d{7}/ # +31(0)20-1234567
# ..etc..
]
def check_number(num):
for pattern in phone_no_patterns:
if num matches pattern:
return match.groups
Затем вы просто перебираете каждый шаблон, проверяя, соответствует ли каждый из них ..
Разделение шаблонов позволяет легко исправить определенные числа, вызывающие проблемы (что было бы ужасно с одним монолитным регулярным выражением).
Это не оптимизация, но вы используете
(-)?( )?
три раза в вашем регулярном выражении. Это заставит вас сопоставить такие номера телефонов
+31(0)6-12345678
+31(0)6 12345678
но также будет соответствовать числам, содержащим тире, за которым следует пробел, например
+31(0)6- 12345678
Вы можете заменить
(-)?( )?
с
(-| )?
чтобы соответствовать либо тире или же, либо пробелу.
Так лучше. Ваше решение спасает персонажа. Я экономил на печатании. :)
(31 | 32) выглядит плохо. При сопоставлении 32 механизм регулярных выражений сначала попытается сопоставить 31 (2 символа), потерпит неудачу и вернет два символа назад, чтобы сопоставить 31. Более эффективно сначала сопоставить 3 (один символ), попробовать 1 (сбой), выполнить возврат одного символа и матч 2.
Конечно, ваше регулярное выражение не работает с номерами 0800-; это не 10 цифр.
Мне не нужны номера 0800, но другая часть вашего комментария была полезной, спасибо.
Первое наблюдение: чтение регулярного выражения - кошмар. Он требует режима Perl / x.
Второе наблюдение: в выражении много, и много, и много захватывающих скобок (42, если я правильно посчитал; а 42, конечно же, «Ответ на жизнь, Вселенную и все» - см. Дуглас Адамс ») Автостопом по Галактике », если вам нужно это объяснять).
Ящерица Билл отмечает, что вы несколько раз использовали «(-)?( )?». У этого нет очевидного преимущества по сравнению с '-? ?' или, возможно, '[- ]?', если только вы действительно не намерены фиксировать фактическую пунктуацию отдельно (но существует так много захватывающих скобок, которые определяют, какие элементы '$ п' использовать было бы сложно) .
Итак, попробуем отредактировать копию вашего однострочного письма:
( |^|>)
(
((((((\+|00)(31|32)( )?(\(0\))?)|0)([0-9]{2})(-)?( )?)?)([0-9]{7})) |
((((((\+|00)(31|32)( )?(\(0\))?)|0)([0-9]{3})(-)?( )?)?)([0-9]{6})) |
((((((\+|00)(31|32)( )?(\(0\))?)|0)([0-9]{1})(-)?( )?)?)([0-9]{8}))
)
( |$|<)
Хорошо - теперь мы можем видеть регулярную структуру вашего регулярного выражения.
Отсюда возможен гораздо больший анализ. Да, регулярное выражение может быть значительно улучшено. Первый, очевидный, состоит в том, чтобы извлечь часть международного префикса и применить ее один раз (необязательно или потребовать ведущий ноль), а затем применить национальные правила.
( |^|>)
(
(((\+|00)(31|32)( )?(\(0\))?)|0)
(((([0-9]{2})(-)?( )?)?)([0-9]{7})) |
(((([0-9]{3})(-)?( )?)?)([0-9]{6})) |
(((([0-9]{1})(-)?( )?)?)([0-9]{8}))
)
( |$|<)
Затем мы можем упростить пунктуацию, как отмечалось ранее, и удалить некоторые вероятные избыточные скобки и улучшить распознаватель кода страны:
( |^|>)
(
(((\+|00)3[12] ?(\(0\))?)|0)
(((([0-9]{2})-? ?)?)[0-9]{7}) |
(((([0-9]{3})-? ?)?)[0-9]{6}) |
(((([0-9]{1})-? ?)?)[0-9]{8})
)
( |$|<)
Мы можем заметить, что регулярное выражение не применяет правила для кодов мобильных телефонов (поэтому оно не требует, например, чтобы за «06» следовало 8 цифр). Также кажется, что 1, 2 или 3-значный «обменный» код может быть необязательным, даже с международным префиксом - вероятно, не то, что вы имели в виду, и исправление этого удаляет еще несколько круглых скобок. После этого мы можем убрать еще несколько скобок, что приведет к следующему:
( |^|>)
(
(((\+|00)3[12] ?(\(0\))?)|0) # International prefix or leading zero
([0-9]{2}-? ?[0-9]{7}) | # xx-xxxxxxx
([0-9]{3}-? ?[0-9]{6}) | # xxx-xxxxxx
([0-9]{1}-? ?[0-9]{8}) # x-xxxxxxxx
)
( |$|<)
И я надеюсь, что отсюда вы сможете поработать над дальнейшей оптимизацией.
спасибо, я разбил это для себя, чтобы посмотреть, смогу ли я достичь этого, но я, должно быть, сделал что-то не так ... спасибо, это действительно полезно
очень старая шишка, но я только что видел часть про 42 ... это хорошо: P Ура, приятель: P
как вы можете заставить это работать с PHP и preg_replace?
Мой первый вопрос: действительно ли вам нужны ВСЕ эти снимки? Разве вы не можете просто взять важные части и переформатировать. Какие уместные части?