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

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

Жанры

Программирование на языке 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
в конце выражения, он позволяет проводить сопоставление без учета регистра. Каждой группе соответствует массив, поэтому в результате получается массив массивов.

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

Имперец. Том 5

Романов Михаил Яковлевич
4. Имперец
Фантастика:
попаданцы
альтернативная история
аниме
6.20
рейтинг книги
Имперец. Том 5

Бухгалтерский учет

Drongelen Wim Van
Деловая литература:
бухучет и аудит
5.00
рейтинг книги
Бухгалтерский учет

Монстр из прошлого тысячелетия

Еслер Андрей
5. Соприкосновение миров
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Монстр из прошлого тысячелетия

Вожделеющее семя

Берджесс Энтони
Проза:
современная проза
6.43
рейтинг книги
Вожделеющее семя

Дикое поле

Веденеев Василий Владимирович
Приключения:
исторические приключения
8.29
рейтинг книги
Дикое поле

Каратила

Поповский Андрей Владимирович
Детективы:
боевики
6.50
рейтинг книги
Каратила

Иисус неизвестный

Мережковский Дмитрий Сергеевич
Научно-образовательная:
философия
4.00
рейтинг книги
Иисус неизвестный

Постмодернизм

Грицанов Александр Алексеевич
Научно-образовательная:
философия
6.25
рейтинг книги
Постмодернизм

Князь Андер Арес 3

Грехов Тимофей
3. Андер Арес
Фантастика:
рпг
аниме
фэнтези
5.00
рейтинг книги
Князь Андер Арес 3

Воплощение Похоти

Некрасов Игорь
1. Воплощение Похоти
Фантастика:
юмористическое фэнтези
попаданцы
рпг
аниме
5.00
рейтинг книги
Воплощение Похоти

Шакалы

Леонов Николай Иванович
18. Гуров
Детективы:
полицейские детективы
7.36
рейтинг книги
Шакалы

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

Винокуров Юрий
15. Кодекс Охотника
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга XV

Наследие Маозари 7

Панежин Евгений
7. Наследие Маозари
Фантастика:
боевая фантастика
юмористическое фэнтези
постапокалипсис
рпг
фэнтези
эпическая фантастика
5.00
рейтинг книги
Наследие Маозари 7

Внук сотника

Красницкий Евгений Сергеевич
1. Отрок
Приключения:
исторические приключения
9.01
рейтинг книги
Внук сотника