2016-11-16 2 views
1

У меня есть строки, как показано нижематч регулярного выражения в рубин

201-Grandview-Dr_Early_TX_76802 и /50-Washington-St

Я пишу регулярное выражение, чтобы соответствовать как строки.

((/^([0-9]+)-([^_]+)-([A-Za-z]{1,})$/ =~ data) == 0) 

Но выше регулярное выражение соответствует только 50-Washington-St, а не второй.

Так что может быть неправильно в этом регулярном выражении.?

Обновленный список строк, которые должны соответствовать:

201-Grandview-Dr_Early_TX_76802 
/50-Washington-St 
49220-Sunrose-Ln_Palm-Desert_CA_92260 
201-Grandview-Dr_Early_TX_76802 
50-Washington-St 
+0

Что такое правило, закономерность? –

+0

Что именно вы хотите совместить? –

+0

@NickolayKondratenko Я хочу совместить строки. строки с дефисами, а также строки с символами подчеркивания и цифры в конце – rubyist

ответ

5

Вы можете исправить регулярное выражение как

/^\/?([0-9]+)-(.+?)-(\w+)$/ 

или померяться всю строку (виду ^ соответствует линии старт и $ конец линии в рубине regex):

/\A\/?([0-9]+)-(.+?)-(\w+)\z/ 

См детализирует Rubular demo

Pattern:

  • \A - строка запуска
  • \/? - необязательный /
  • ([0-9]+) - Группа 1: одну или несколько цифр
  • - - дефис
  • (.+?) - Группа 2: один или несколько отличных LineBreak символов
  • - символы - дефис
  • (\w+) - Группа 3: один или несколько слов ([A-Za-z0-9_]) символы
  • \z - конец строки.
+0

Stribizew, но он не передает «/ 50-Washington-St» с вашим регулярным выражением – rubyist

+0

Зачем это нужно? Он не похож на строки в вашем вопросе. Но вы можете добавить '\ W *' (если вы хотите разрешить любое количество символов без слов в начале) или '\ /?' (Чтобы разрешить необязательный '/') сразу после '^' или '\ A'. –

+0

в порядке. К сожалению, это была ошибка опечатки – rubyist

0

Я хотел бы предложить способ решения таких проблем, как этот. Основной вывод заключается в том, что сложные регулярные выражения могут быть построены так же, как и другой код Ruby: создавать небольшие модули кода, которые можно легко протестировать, а затем объединить эти модули.

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

s = "201-Grandview-Dr_Early_TX_76802" 

Поскольку эта строка не содержит символов, которые должны быть экранированы, мы можем создать регулярное выражение, которое будет точно соответствовать этой строке, просто заменив двойные кавычки с косой черты и добавления их запуска из-строки (\A) и с истекшим струне (\z) якоря:

r = /\A201-Grandview-Dr_Early_TX_76802\z/ 
    #=> /\A201-Grandview-Dr_Early_TX_76802\z/ 
s =~ r 
    #=> 0 

Это то, что мы имеем:

/\A201-Grandview\-Dr_Early_TX_76802\z/ 
    ⬆︎street number 
      ⬆︎street name 
        ⬆︎street name suffix 
         ⬆︎city 
          ⬆︎state 
           ⬆︎zip 

Предположительно регулярное выражение должно мат ch строка, если и только если строка содержит допустимые значения для каждого из этих шести полей и имеет форматирование, показанное между соседними полями.

Начнем с выделения отдельного регулярного выражения для каждого из шести полей. Естественно, что все эти регулярные выражения могут нуждаться в модификации в соответствии с требованиями.

Улица номер

Типичной улица номер может быть "221", "22", "221b". Предположим, у нас также могут быть «A19» или «221BZ», но не «221-B». Тогда мы могли бы написать:

number = /[[:alnum:]]+/ 

(. Найти "POSIX" в Regexp) Название

Street

я предположил, что названия улиц состоят из одного слова или нескольких слов, разделенных одиночное пространство, где каждое слово имеет все строчные буквы, кроме первой буквы, которая заглавная.

street = /[[:upper:]][[:lower:]]+(?:\s[[:upper:]][[:lower:]]+)*/ 

/[[:upper:]][[:lower:]]+ соответствует первому слову, (?:\s[[:upper:]][[:lower:]])* соответствует пробелу, затем заглавным слово, повторяется ноль или более раз ((?:...) не-захват группа. Задний * означает повторить ноль или более раз.)

название улицы суффикс

я предположил, что суффикс названия улицы (например, «Улица», «St.«) Является одним словом, все в нижнем регистре, за исключением первого символа, который в верхнем регистре, необязательно заканчивается период:

suffix = /[[:upper:]][[:lower:]]+\.?/ 

Сити

Я предположил, что названия городов имеет то же самое требования, как сделать название улиц:

city = street 
    #=> /[[:upper:]][[:lower:]]+(?:\s[[:upper:]][[:lower:]]+)*/ 

государственного

государств определяются двумя прописными буквами:

state = /[[:upper:]]{2}/ 

Мы могли бы быть более точным, написав:

state = Regexp.union %w| AL AK AZ ... | 

, но тогда нам придется обновлять его каждый раз, когда территория стала новым государством или (возможно, из-за недавних событий) государство отделяется от союза.

Почтовый индекс

Zip коды пять цифр или девять цифр с тире или дефис после первых четырех цифр.

zip = /\d{5}(?:-\d{4})?/ 

Использование

/\A201-Grandview-Dr_Early_TX_76802\z/ 

как наш шаблон, наше общее регулярное выражение, поэтому следующее:

r1 =/
    \A # match start of string 
    #{number} 
    - 
    #{street} 
    - 
    #{suffix} 
    _ 
    #{city} 
    _ 
    #{state} 
    _ 
    #{zip} 
    \z # match end of string 
    /x # free-spacing regex definition mode 
    #=>/
    # \A # match start of string 
    # /(?-mix:[[:alnum:]]+) 
    # - 
    # (?-mix:[[:upper:]][[:lower:]]+(?:\s[[:upper:]][[:lower:]]+)*) 
    # - 
    # (?-mix:[[:upper:]][[:lower:]]+\.?) 
    # _ 
    # (?-mix:[[:upper:]][[:lower:]]+(?:\s[[:upper:]][[:lower:]]+)*) 
    # _ 
    # (?-mix:[[:upper:]]{2}) 
    # _ 
    # (?-mix:\d{5}(?:-\d{4})?) 
    # \z # match start of string 
    /x 

Давайте попробуем для первой строки и их вариации:

"201-Grandview-Dr_Early_TX_76802" =~ r1 
    #=> 0 
"221B-Grand View-Dr._El Paso_TX_76802-0000" =~ r1 
    #=> 0 
"2A0B1-Grandview-Dr_Early_ZZ_76802" =~ r1 
    #=> 0 
"201-GrandView-Dr_Early_TX_76802" =~ r1 
    #=> nil 
"201-Grandview-Dr_Early_TX_7680" =~ r1 
    #=> nil 
"201-Pi11ar-St_Early_TX_76802" =~ r1 
    #=> nil 
"I live at 201-Grandview-Dr_Early_TX_76802" =~ r1 
    #=> nil 
"201-mg Circle-Lane_Early_TX_76802" =~ r1 
    #=> nil 

Теперь рассмотрим второй Пример строки, для которых должен быть матч:

"/50-Washington-St" 

Мы видим регулярное выражение для этого просто

r2 =/
    \A 
    \/ 
    #{number} 
    - 
    #{street} 
    - 
    #{suffix} 
    \z 
    /x 
#=>/
# \A 
# \/ 
# (?-mix:[[:alnum:]]+) 
# - 
# (?-mix:[[:upper:]][[:lower:]]+(?:\s[[:upper:]][[:lower:]]+)*) 
# - 
# (?-mix:[[:upper:]][[:lower:]]+\.?) 
# \z 
# /x 

Давайте попробуем.

"/50-Washington-St" =~ r2 
    #=> 0 
"50-Washington-St" =~ r2 
    #=> nil 
"/50-Washington-St_Early" =~ r2 
    #=> nil 

Так что теперь наше общее регулярное выражение просто

r = Regexp.union(r1,r2) 
    #=> /(?x-mi: 
    # \A # match start of string 
    # (?-mix:[[:alnum:]]+) 
    # - 
    # (?-mix:[[:upper:]][[:lower:]]+(?:\s[[:upper:]][[:lower:]]+)*) 
    # - 
    # (?-mix:[[:upper:]][[:lower:]]+\.?) 
    # _ 
    # (?-mix:[[:upper:]][[:lower:]]+(?:\s[[:upper:]][[:lower:]]+)*) 
    # _ 
    # (?-mix:[[:upper:]]{2}) 
    # _ 
    # (?-mix:\d{5}(?:-\d{4})?) 
    # \z # match end of string 
    # )|(?x-mi: 
    # \A 
    # \/ 
    # (?-mix:[[:alnum:]]+) 
    # - 
    # (?-mix:[[:upper:]][[:lower:]]+(?:\s[[:upper:]][[:lower:]]+)*) 
    # - 
    # (?-mix:[[:upper:]][[:lower:]]+\.?) 
    # \z 
    # )/ 

"201-Grandview-Dr_Early_TX_76802" =~ r 
    #=> 0 
"/50-Washington-St" =~ r 
    #=> 0 
Смежные вопросы