2013-09-26 2 views
0

Я пытаюсь решить проблему №6 из книги Ruby Quiz. Эта проблема говорит, что я должен создать новый метод под названием build() для класса Regex, в котором, передавая целые числа или диапазоны, он должен генерировать регулярное выражение для определения разрешенных чисел.Как создать регулярные выражения для определения целых чисел и диапазонов?

Например:

lucky = Regexp.build(3, 7) 
"7" =~ lucky # => true 
"13" =~ lucky # => false 
"3" =~ lucky # => true 

month = Regexp.build(1..12) 
"0" =~ month # => false 
"1" =~ month # => true 
"12" =~ month # => true 

Я разработал багги версию, но она не работает, как ожидалось. Моя проблема заключается в генерации правильного регулярного выражения. Все шаблоны, которые я пробовал в Rubular, не принимают то, что им нужно. Например, для Regexp.build(1, 3, 5) я получил образец, который выглядит как этот:

/^1|3|5$/ 

Это работает, и это соответствует 1, 3 и 5. Но он также соответствует 15 или 13.

Каков наилучший способ, чтобы цифры не объединялись между ними?

---- EDIT

Использование групп, теперь, кажется, работает правильно. В любом случае, есть ли способ получить regexp, представляющий диапазон? Например, сохраняя предыдущий пример:

lucky = Regexp.build(1..12) 
"7" =~ lucky # => true 
"13" =~ lucky # => false 
"0" =~ lucky # => false 
"5" =~ lucky # => true 

Регулярное выражение, порожденный Regexp.build бы, чтобы соответствовать все значения между 1 и 12, но не более. Я искал в Интернете, и я видел, что сложно создать этот тип регулярного выражения программным путем. Есть ли какой-либо конкретный или предопределенный метод для этой задачи?

http://utilitymill.com имеет рекурсивную функцию для достижения этого, но я считаю это довольно сложным.

+0

** Регулярные выражения для сопоставления с шаблоном, не проверяя числовые значения. ** Найдите вероятную строку с регулярным выражением, а затем проверить его числовое значение независимо от вашего языка хоста (Ruby, что угодно). –

ответ

1

Небольшая подсказка:

/^1|3|5$/ 

означает

/^1/ или /3/ или /5$/

Посмотрите в groups. Они помогут вам удостовериться, что в сферу чередования не включены ваши якоря начала/конца.

+0

В этом была проблема. Теперь регулярное выражение, похоже, работает =) –

0

Вы хотите совместить уникальный элемент, который находится в начале и конце. Это может быть достигнуто путем группировки с помощью круглых скобок. Например: /^(1|3|5)$/

0

Проблема заключается в том, что ваш шаблон позволяет совпадать с одним словом (in-number?). Я хотел бы использовать это:

/\b(?:3|7)\b/ 

Это только позволяет одиночные буквы 3 или 7.

Испытано на: http://rubular.com/r/0rRUfXdlTJ

Этот шаблон будет работать на автономном значении, или числа встроенных в строку.

\b - это маркеры на основе слов, то есть должен быть переход от неглавного слова к слову.Слово [a-zA-Z0-9_].

Используя тесты:

"7" =~ /\b(?:3|7)\b/ # => 0 
"13" =~ /\b(?:3|7)\b/ # => nil 
"3" =~ /\b(?:3|7)\b/ # => 0 

"0" =~ /\b(?:1|2|3|4|5|6|7|8|9|10|11|12)\b/ # => nil 
"1" =~ /\b(?:1|2|3|4|5|6|7|8|9|10|11|12)\b/ # => 0 
"12" =~ /\b(?:1|2|3|4|5|6|7|8|9|10|11|12)\b/ # => 0 

Где => 0 означает образец согласованный на первом индексе символов и nil был промах.

Это говорит о том, что я бы не попытался использовать шаблон для обеспечения диапазона, потому что это пытается сделать их во что-то, что им действительно не подходит. Взгляните на шаблоны, используемые для проверки допустимых номеров IPv4, или, что еще хуже, на номер IPv6. Для реальной забавы посмотрите на the pattern for a valid email address. У всех есть спецификации, определяющие то, что является действительными значениями, но шаблоны для их определения свернуты и за пределами смертных людей. Вместо этого используйте шаблон для поиска вещей, которые выглядят как цифры, извлекают это значение и проверяют, находится ли он в допустимом диапазоне.

Например, вот шаблон IPv4 из Резолв :: IPv4 :: Regex в Ruby:

/\A((?x-mi:0 
       |1(?:[0-9][0-9]?)? 
       |2(?:[0-4][0-9]?|5[0-5]?|[6-9])? 
       |[3-9][0-9]?))\.((?x-mi:0 
       |1(?:[0-9][0-9]?)? 
       |2(?:[0-4][0-9]?|5[0-5]?|[6-9])? 
       |[3-9][0-9]?))\.((?x-mi:0 
       |1(?:[0-9][0-9]?)? 
       |2(?:[0-4][0-9]?|5[0-5]?|[6-9])? 
       |[3-9][0-9]?))\.((?x-mi:0 
       |1(?:[0-9][0-9]?)? 
       |2(?:[0-4][0-9]?|5[0-5]?|[6-9])? 
       |[3-9][0-9]?))\z/ 

Более длинные значения, как IPv6 это сделать еще сложнее. См. Regular expression that matches valid IPv6 addresses для получения дополнительной информации. Поэтому моя рекомендация состоит в том, чтобы использовать регулярные выражения для простых вещей и использовать то, что им хорошо - извлекать значения, соответствующие шаблону, а затем использовать дополнительный код для проверки того, что они находятся в зоне действия или действительно являются действительными.

2
/(^|\D)1(\D|$)|(^|\D)3(\D|$)|(^|\D)5(\D|$)/ 

это регулярное выражение код соответствует 1 3 5 по-другому, это не соответствует 13 и 15.

Если я неправильно понять любую вещь, то объясните мне подробно, что вы хотите.

поблагодарить вас

Смежные вопросы