Чтение онлайн

на главную - закладки

Жанры

Программирование на языке Ruby
Шрифт:

rom1 = /m{0,3}/i

rom2 = /(d?c{0,3}|с[dm])/i

rom3 = /(l?x{0,3}|x[lс])/i

rom4 = /(v?i{0,3}|i[vx])/i

roman = /^#{rom1}#{rom2}#{rom3}#{rom4}$/

year1985 = "MCMLXXXV"

if year1985 =~ roman # Печатается: "да"

 puts "да"

else

 puts "нет"

end

Возможно, у вас появилось искушение поставить в конец всего выражения модификатор

i
, чтобы сопоставлялись и строчные буквы:

# Это не работает!

rom1 = /m{0,3}/

rom2 = /(d?c{0,3}|с[dm])/

rom3 = /(l?x{0,3}|x[lс])/

rom4 = /(v?i{0,3}|i[vx])/

roman = /^#{rom1}#{rom2}#{rom3}#{rom4}$/i

Почему такое выражение не годится? Взгляните на этот пример и поймете:

rom1.to_s # "(?-mix:m{0,3})"

Обратите внимание, что метод

to_s
запоминает флаги для каждого выражения; тем самым флаг всего выражения перекрывается.

3.14.4 Сопоставление с числовыми константами

Сопоставление с простым целым десятичным числом — самое простое. Число состоит из необязательного знака и последовательности цифр (правда, Ruby позволяет использовать знак подчеркивания в качестве разделителя цифр). Отметим, что первая цифра не должна быть нулем, иначе число будет интерпретироваться как восьмеричное.

int_pat = /^[+-]?[1-9][\d_]*$/

Целые константы в других системах счисления обрабатываются аналогично. Образцы для шестнадцатеричных и двоичных чисел сделаны не чувствительными к регистру, так как они содержат букву:

hex_pat = /^[+-]?0x[\da-f_]+$/i

oct_pat = /^[+-]?0[0-7_]+$/

bin_pat = /^[+-]?0b[01_]+$/i

Сопоставить число с плавающей точкой в обычной нотации несколько сложнее. Последовательности цифр по обе стороны десятичной точки необязательны, но хотя бы одна цифра должна быть:

float_pat = /^(\d[\d_]*)*\.[\d_]*$/

Образец для чисел, записанных в научной нотации, основан на предыдущем:

sci_pat = /^(\d[\d_]*)?\.[\d_]*(e[+-]?)?(_*\d[\d_]*)$/i

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

3.14.5 Сопоставление с датой и временем

Пусть надо выделить дату и время, записанные в формате

mm/dd/yy hh:mm:ss
. Вот первая попытка:
datetime = /(\d\d)\/(\d\d)\/(\d\d) (\d\d): (\d\d): (\d\d)/
.

Но такой образец распознает некоторые некорректные даты и отвергает правильные. Следующий вариант более избирателен. Обратите внимание, как мы строим его путем интерполяции мелких регулярных выражений в более крупное:

mo = /(0?[1-9]|1[0-2])/ # От 01 до 09 или от 1 до 9 или 10-12.

dd = /([0-2]?[1-9]| [1-3][01])/ # 1-9 или 01-09 или 11-19 и т.д.

yy = /(\d\d)/ # 00-99

hh = /([01]?[1-9]|[12][0-4])/ # 1-9 или 00-09 или...

mi = /([0-5]\d)/ # 00-59, обе цифры должны присутствовать.

ss = /([0-6]\d)?/ # разрешены еще и доли секунды ;-)

date = /(#{mo}\/#{dd}\/#{yy})/

time = /{#{hh}:#{mi}:#{ss})/

datetime = /(#{date} #{time})/

Вот как можно вызвать это регулярное выражение из метода

String#scan
, чтобы получить массив соответствий:

str="Recorded on 11/18/07 20:31:00"

str.scan(datetime)

# [["11/18/07 20:31:00", "11/18/07", "11", "18", "00",

# "20:31:00", "20", "31", ":00"]]

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

datetime = %r{(

 (0?[1-9]|1[0-2])/ # mo: от 01 до 09 или от 1 до 9 или 10-12.

 ([0-2]?[1-9]|[1-3][01])/ # dd: 1-9 или 01-09 или 11-19 и т. д.

 (\d\d) [ ] # yy: 00-99

 ([01]?[1-9]|[12][0-4]): # hh: 1-9 или 00-09 или...

 ([0-5]\d): # mm: 00-59, обе цифры должны присутствовать.

 (([0-6]\d))? # ss: разрешены еще и доли секунды ;-)

)}x

Обратите внимание на конструкцию

%r{}
, позволяющую не экранировать символы обратной косой черты.

3.14.6. Обнаружение повторяющихся слов в тексте

В этом разделе мы реализуем детектор повторяющихся слов. Повторение одного и того же слова два раза подряд — типичная опечатка. Следующий код распознает такие ситуации:

double_re = /\b(['A-Z]+) +\1\b/i

str="There's there's the the pattern."

str.scan(double_re) # [["There's"],["the"]]

Обратите внимание на модификатор

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

Поделиться:
Популярные книги

Бастард

Осадчук Алексей Витальевич
1. Последняя жизнь
Фантастика:
фэнтези
героическая фантастика
попаданцы
5.86
рейтинг книги
Бастард

Наследник павшего дома. Том II

Вайс Александр
2. Расколотый мир [Вайс]
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Наследник павшего дома. Том II

Некурящий. Трилогия

Федотов Антон Сергеевич
Некурящий
Фантастика:
фэнтези
боевая фантастика
попаданцы
5.00
рейтинг книги
Некурящий. Трилогия

Виктор Глухов агент Ада. Компиляция. Книги 1-15

Сухинин Владимир Александрович
Виктор Глухов агент Ада
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
попаданцы
5.00
рейтинг книги
Виктор Глухов агент Ада. Компиляция. Книги 1-15

Моров. Том 7

Кощеев Владимир
6. Моров
Фантастика:
альтернативная история
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Моров. Том 7

Мастер 8

Чащин Валерий
8. Мастер
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Мастер 8

Кодекс Охотника. Книга XXXIX

Сапфир Олег
39. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
боевая фантастика
5.00
рейтинг книги
Кодекс Охотника. Книга XXXIX

Последний Герой. Том 3

Дамиров Рафаэль
3. Последний герой
Фантастика:
попаданцы
альтернативная история
фантастика: прочее
5.00
рейтинг книги
Последний Герой. Том 3

Камень

Минин Станислав
1. Камень
Фантастика:
боевая фантастика
6.80
рейтинг книги
Камень

Школа пластунов

Трофимов Ерофей
Одиночка
Фантастика:
боевая фантастика
5.00
рейтинг книги
Школа пластунов

Я уже граф. Книга VII

Дрейк Сириус
7. Дорогой барон!
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Я уже граф. Книга VII

Вечный. Книга II

Рокотов Алексей
2. Вечный
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Вечный. Книга II

Последний Герой. Том 2

Дамиров Рафаэль
2. Последний герой
Фантастика:
попаданцы
альтернативная история
4.50
рейтинг книги
Последний Герой. Том 2

Вернувшийся: Посол. Том IV

Vector
4. Вернувшийся
Фантастика:
космическая фантастика
киберпанк
5.00
рейтинг книги
Вернувшийся: Посол. Том IV