Страница 47 из 53
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]]/ # Задает пересечение.
А следующее выражение соответствует всему алфавиту, кроме букв от m до p:
reg2 = /[a-z&&[^m-р]]/
Поскольку такие выражения выглядят не очень понятно, рекомендую пользоваться этим средством осмотрительно.
Другие возможности Oniguruma, например оглядывание назад и именованные соответствия, будут рассмотрены ниже. Все связанное с интернационализацией отложим до главы 4.
3.13.4 Позитивное и негативное оглядывание назад
Если заглядывания вперед вам недостаточно, то Oniguruma предлагает еще и оглядывание назад, позволяющее определить, предшествует ли текущему положению заданный образец.
Как и многое другое в регулярных выражениях, эту возможность довольно трудно понять и обосновать. Спасибо Эндрю Джексону за следующий пример.
Предположим, что вам нужно проанализировать некоторую генетическую последовательность (молекула ДНК состоит из четырех основных белков, которые обозначаются А, С, G и T.) Допустим, что мы ищем все неперекрывающиеся цепочки нуклеотидов (длины 4), следующие за T. Нельзя просто попытаться найти T и взять следующие четыре символа, поскольку T может быть последним символом в предыдущем соответствии.
gene = 'GATTACAAACTGCCTGACATACGAA'
seqs = gene.scan(/T(w{4})/)
# seqs равно: [["TACA"], ["GCCT"], ["ACGA"]]
Ho в этом коде мы пропустили цепочку GACA, которая следует за GCCT. Позитивное оглядывание назад позволит найти все нужные цепочки:
gene = 'GATTACAAACTGCCTGACATACGAA'
seqs = gene.scan(/(?<=T)(w{4})/)
# seqs равно: [["TACA"], ["GCCT"], ["GACA"], ["ACGA"]]
Следующий пример - небольшая модификация примера, предложенного К. Косако (К. Kosako). Предположим, что есть текст в формате XML (или HTML), и мы хотим перевести в верхний регистр весь текст вне тегов (то есть cdata) Вот как можно сделать это с помощью оглядывания назад:
text =<<-EOF
<body> <h1>This is a heading</h1>
<p> This is a paragraph with some
<i>italics</i> and some <b>boldface</b>
in it...</p>