Программирование на языке Ruby - Хэл Фултон
Шрифт:
Интервал:
Закладка:
regex = / ^ # Начало строки.
((No.?)s+)? # Необязательно: No[.]
d+ s+ # Цифры и пробелы.
((w|[.'-])+ # Название улицы... может
s* # состоять из нескольких слов.
)+
(,s* # Необязательно: запятая и т.д.
(Apt.?|Suite|#) # Apt[.], Suite, #
s+ # Пробелы.
(d+|[A-Z]) # Цифры или одна буква.
)?
$ # Конец строки.
/x
Идея понятна. Когда сложность регулярного выражения достигает некоего порога (какого именно — дело вкуса), делайте его обобщенным, чтобы можно было добавить форматирование и комментарии.
Возможно, вы заметили, что я пользовался обычными комментариями Ruby (# ...), а не специальными, применяемыми в регулярных выражениях ((?#...)). Почему? Просто потому, что это разрешено! Специальный комментарий необходим только тогда, когда его следует закончить раньше конца строки (например, если в той же строке за комментарием продолжается регулярное выражение).
3.10. Сопоставление точки символу конца строки
Обычно точка соответствует любому символу, кроме конца строки. Если задан модификатор многострочности m, точка будет сопоставляться и с этим символом. Другой способ — задать флаг Regexp::MULTILINE при создании регулярного выражения:
str = "Rubies are rednAnd violets are blue.n"
pat1 = /red./
pat2 = /red./m
str =~ pat1 # nil
str =~ pat2 # 11
Этот режим не оказывает влияния на то, где устанавливается соответствие якорям (^, $, A, Z). Изменяется только способ сопоставления с точкой.
3.11. Внутренние модификаторы
Обычно модификаторы (например, i или m) задаются после регулярного выражения. Но что если мы хотим применить модификатор только к части выражения?
Существует специальная нотация для включения и выключения модификаторов. Заключенный в круглые скобки вопросительный знак, за которым следует один или несколько модификаторов, «включает» их до конца регулярного выражения. А если некоторым модификаторам предшествует минус, то соответствующие режимы «выключаются»:
/abc(?i)def/ # Соответствует abcdef, abcDEF, abcDef,
# но не ABCdef.
/ab(?i)cd(?-i)ef/# Соответствует abcdef, abCDef, abcDef, ...,
# но не ABcdef или abcdEF.
/(?imx).*/ # To же, что /.*/imx
/abc(?i-m).*/m # Для последней части регулярного выражения включить
# распознавание регистра, выключить многострочный
# режим.
При желании можно поставить перед подвыражением двоеточие, и тогда заданные модификаторы будут действовать только для этого подвыражения:
/ab(?i:cd)ef/ # То же, что /ab(?i)cd(?-i)ef/
По техническим причинам использовать таким образом модификатор о нельзя. Модификатор x — можно, но я не знаю, кому бы это могло понадобиться.
3.12. Внутренние подвыражения
Для указания подвыражений применяется нотация ?>:
re = /(?>abc)(?>def)/ # То же, что /abcdef/
re.match("abcdef").to_a # ["abcdef"]
Отметим, что наличие подвыражения еще не означает группировки. С помощью дополнительных скобок их, конечно, можно превратить в запоминаемые группы.
Еще обратим внимание на то, что эта конструкция собственническая, то есть жадная и при этом не допускает возврата в подвыражение.
str = "abccccdef"
re1 = /(abc*)cdef/
re2 = /(?>abc*)cdef/
re1 =~ str # 0
re2 =~ str # nil
re1.match(str).to_a # ["abccccdef", "abccc"]
re2.match(str).to_a # []
В предыдущем примере подвыражение abc* выражения re2 поглощает все вхождения буквы с и (в соответствии с собственническим инстинктом) не отдает их назад, препятствуя возврату.
3.13. Ruby и Oniguruma
Новая библиотека регулярных выражений в Ruby называется Oniguruma. Это японское слово означает что-то вроде «колесо духов». (Те, кто не владеет японским, часто пишут его неправильно; имейте в виду, что тут не обойтись без «guru»!)
Новая библиотека превосходит старую в нескольких отношениях. Прежде всего, она лучше работает с иноязычными строками, а также добавляет кое-какие интересные возможности к регулярным выражениям. Наконец, лицензия на ее использование мягче, чем на использование Ruby в целом. Когда писалась эта книга, Oniguruma еще не была полностью интегрирована в Ruby.
В следующем разделе мы расскажем, как определить, присутствует ли библиотека Oniguruma. А затем покажем, как можно ее собрать, если она не включена в дистрибутив.
3.13.1. Проверка наличия Oniguruma
Если вас интересует библиотека Oniguruma, то первым делом нужно выяснить, есть ли она в вашем экземпляре Ruby. В версиях 1.8.4 и младше ее, скорее всего, нет. Стандартно она включается в дистрибутив версии 1.9.
Вот как можно без труда выяснить, присутствует ли Oniguruma, проверив три условия. Во-первых, как я сказал, она стандартно поставляется в версии 1.9 и старше. В последних версиях обеих библиотек для работы с регулярными выражениями определена строковая константа Regexp::ENGINE. Если она содержит подстроку Oniguruma, то у вас новая библиотека. И последний шаг: если вы все еще не знаете, с какой библиотекой работаете, можно попытаться вычислить регулярное выражение, записанное в «новом» синтаксисе. Если при этом возникнет исключение SyntaxError, значит, у вас старая библиотека; в противном случае — новая.
def oniguruma?
return true if RUBY_VERSION >= "1.9.0"
if defined?(Regexp::ENGINE) # Константа ENGINE определена?
if Regexp::ENGINE.include?('Oniguruma')
return true # Какая-то версия Oniguruma.
else
return false # Старая библиотека,
end
end
eval("/(?<!a)b/") # Новый синтаксис.
return true # Сработало: новая библиотека.
rescue SyntaxError # Не сработало: старая библиотека.
return false
end
puts oniguruma?
3.13.2. Сборка Oniguruma
Если в вашу версию библиотека Oniguruma не включена, можете самостоятельно откомпилировать Ruby и скомпоновать с недостающей библиотекой. Ниже приведены соответствующие инструкции. Эта процедура должна работать начиная с версии 1.6.8 (хотя она уже совсем старенькая).
Получить исходный текст Oniguruma можно из архива приложений Ruby RAA (http://raa.ruby-lang.org/) или найти в другом месте. Исходные тексты Ruby, естественно, находятся на официальном сайте.
Если вы работаете на платформе UNIX (в том числе в среде Cygwin в Windows или Mac OS/X), выполните следующие действия:
1. gunzip oniguruma.tar.gz
2. tar xvf oniguruma.tar
3. cd oniguruma
4. ./configure with-rubydir=<ruby-source-dir>
5. Одно из следующих:
make 16 # Для Ruby 1.6.8
make 18 # Для Ruby 1.8.0/1.8.1
6. cd ruby-source-dir
7. ./configure
8. make clean
9. make
10. make test # Простой тест интерпретатора Ruby.
11. cd ../oniguruma # Укажите путь к библиотеке.
12. make rtest
Или:
make rtest RUBYDIR=ruby-install-dir
Если же вы работаете на платформе Win32, скажем в Windows XP, то потребуются Visual C++ и исполняемый файл patch.exe. Выполните следующие действия:
1. Распакуйте архив любой имеющейся у вас программой.
2. copy win32Makefile Makefile
3. Одно из следующих:
nmake 16 RUBYDIR=ruby-source-dir # для Ruby 1.6.8
nmake 18 RUBYDIR=ruby-source-dir # для Ruby 1.8.0/1.8.1
4. Следуйте инструкции в файле ruby-source-dirwin32README.win32.
При возникновении ошибок обратитесь в список рассылки или конференцию.
3.13.3. Некоторые новые возможности Oniguruma
Oniguruma добавляет много новых возможностей к механизму работы с регулярными выражениями в Ruby. Из самых простых отметим дополнительную управляющую последовательность для указания класса символов. Если d и D соответствуют десятичным цифрам и не цифрам, то h и H являются аналогами для шестнадцатеричных цифр:
"abc" =~ /h+/ #0
"DEF" =~ /h+/ # 0
"abc" =~ /Н+/ # nil
Добавилось возможностей у классов символов в квадратных скобках. Для организации вложенных классов можно применять оператор &&. Вот как можно записать регулярное выражение, соответствующее любой букве, кроме гласных а, е, i, о, u:
reg1 = /[a-z&&[^aeiou]]/ # Задает пересечение.