Давайте напишем более интересную программу. В этот раз мы проверим, подходит ли строка под описание, закодированное в кратком шаблоне.
Некоторые символы и комбинации символов имеют специальное значение в этих шаблонах, и включают в себя:
[] - определение диапазона (например, [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, если строка не была найдена шаблоном регулярного выражения.