Давайте напишем более интересную программу. В этот раз мы проверим, подходит ли строка под описание, закодированное в кратком шаблоне.
Некоторые символы и комбинации символов имеют специальное значение в этих шаблонах, и включают в себя:
[] - определение диапазона (например, [a-z] означает буквы в диапазоне от a до z
\w - буква или цифра, аналогично [0-9A-Za-z]
\W - не цифра и не буква
\s - символы пустого пространства, такие как [ \t\n\r\f]
\S - не символы пустого пространства
\d - символы цифр, такие как [0-9]
\D - не символы цифр
\b - символ забоя (0x08) (только если в заданном диапазоне)
\b - окончание слова (если только не в заданном диапазоне)
\B - граница слова
* - ноль и большее количество повторений предыдущего шаблона
+ - одно или большее количество повторений предыдущего шаблона
{m,m} - по крайней мере m и не более повторений предыдущего
? - по крайней мере одно повторение предыдущего
| - либо предыдущее, либо последующее выражение может соответствовать
() - группировка
Общим термином для таких шаблонов является Регулярные выражения . В Ruby, как и в Perl, они в основном заключаются в слэши, чем в двойные кавычки. Если Вы никогда не работали с регулярными выражениями до этого, то возможно, имеет смысл потратить некоторое время на знакомство с ними. Они имеют выразительную мощь, которая может спасти вас от головной боли (и множества строчек лишнего кода), если вам понадобится по шаблону сравнивать, искать строки и манипулировать ими.
Например, предположим, что вы хотите проверить, входит ли строка под данное описание: "Начинается с буквы "f" в нижнем регистре, за которой следует одна буква в верхнем регистре, и опционально следует за ней как можно более долгая последовательность символов, пока не встретится буква в нижнем регистре. Если вы являетесь опытным C программистом, то возможно уже написали несколько десятков строк кода в своей голове. Признайтесь в этом; Вы можете себе помочь. Но в Ruby Вам нужно сделать только один запрос к вашей проверяемой строке со следующим регулярным выражением /^f A-Z $/.*
А что думаете о поиске шестнадцатеричного числа, заключённого в треугольные скобки? Без проблем.
ruby> def chab(s) # "contains hex in angle brackets" | (s =~ /<0(x|X)(\d|[a-f]|[A-F])+>/) != nil | end nil ruby> chab "Not this one." false ruby> chab "Maybe this? {0x35}" # wrong kind of brackets false ruby> chab "Or this? <0x38z7e>" # bogus hex digit false ruby> chab "Okay, this: <0xfc0004>." true
Хотя регулярные выражения могут быть и весьма загадочны на первый взгляд, Вы быстро получите отдачу от них.
Вот небольшая программа, которая поможет Вам поэкспериментировать с регулярными выражениями. Сохраните её в файл regx.rb и запустите в командной строке " ruby regx.rb"
# Requires an ANSI terminal! st = "\033[7m" en = "\033[m" while TRUE print "str> " STDOUT.flush str = gets break if not str str.chop! print "pat> " STDOUT.flush re = gets break if not re re.chop! str.gsub! re, "#{st}\\&#{en}" print str, "\n" end print "\n"
Эта программа дважды требует ввода, первый раз строка и второй раз регулярное выражение. Строка проверяется регулярным выражением, и затем выводится с подсвеченными частями, которые соответствуют регулярному выражению.
str> foobar pat> ^fo+ foobar ~~~
Совпадающая часть помечена в листинге следующей линией "~~~".
Давайте попробуем ещё больше вводов.
str> abc012dbcd555 pat> \d abc012dbcd555 ~~~ ~~~
Если Вы удивились выводу программы, то обратитесь к списку в начале статьи: \d обозначает сравнение с одной цифрой.
Что если имеется больше чем один способ правильного сравнения шаблонов?
str> foozboozer pat> f.*z foozboozer ~~~~~~~~
foozbooz было сравнимой последовательностью, вместо просто fooz , с регулярным выражениями возможно сравнение с длинными подстроками.
А вот и пример поиска строки со временем.
str> Wed Feb 7 08:58:04 JST 1996 pat> [0-9]+:[0-9]+(:[0-9]+)? Wed Feb 7 08:58:04 JST 1996 ~~~~~~~~
"=~" является оператором сравнения для регулярных выражений. Он возвращает позицию найденной строки либо nil, если строка не была найдена шаблоном регулярного выражения.