Главная Обратная связь

Дисциплины:






Сопоставление с IP-адресом



Пусть мы хотим понять, содержит ли строка допустимый IPv4-адрес. Стандартно он записывается в точечно-десятичной нотации, то есть в виде четырех десятичных чисел, разделенных точками, причем каждое число должно находиться в диапазоне от 0 до 255.

Приведенный ниже образец решает эту задачу (за немногими исключениями типа «127.1»). Для удобства восприятия мы разобьем его на части. Отметим, что символ \d дважды экранирован, чтобы косая черта не передавалась из строки в регулярное выражение (чуть ниже мы решим и эту проблему).

num = "(\\d|[01]?\\d\\d|2[0-4]\\d\25[0-5])"

pat = ^(#{num}\.){3}#{num}$"

ip_pat = Regexp.new(pat)

 

ip1 = "9.53.97.102"

 

if ip1 =~ ip_pat # Печатается: "да"

puts "да"

else

puts "нет"

end

Надо признать, что в определении переменной num слишком много символов обратной косой черты. Определим ее в виде регулярного выражения, а не строки:

num = /(\d1[01]?\d\d|2[0-4]\d|25[0-5])/

Когда одно регулярное выражение интерполируется в другое, вызывается метод to_s, который сохраняет всю информацию из исходного регулярного выражения.

num.to_s # "(?-mix:(\\d|[01]?\\d\\d|2[0-4]\\d|25[0-5]))"

Иногда для встраивания удобно использовать регулярное выражение, а не строку. Хорошее эвристическое правило: интерполируйте регулярные выражения, если веских причин интерполировать строки.

IPv6-адреса пока не очень широко распространены, но для полноты рассмотрим и их. Они записываются в виде восьми шестнадцатеричных чисел, разделенных двоеточиями, с подавлением начальных нулей.

num = /[0-9A-Fa-f]{0,4}/

pat = /^(#{num}:){7}#{num}$/

ipv6_pat = Regexp.new(pat)

v6ip = "abcd::1324:ea54::dead::beef"

 

if v6ip =~ ipv6_pat # Печатается: "да"

puts "да"

else

puts "нет"

end


3.14.2. Сопоставление с парой «ключ-значение»

Иногда приходится работать со строками вида «ключ=значение» (например, при разборе конфигурационного файла приложения).

Следующий код извлекает ключ и значение. Предполагается, что ключ состоит из одного слова, значение продолжается до конца строки, а знак равенства может быть окружен пробелами:

pat = /(\w+)\s*=\s*(.*?)$/

str = "color = blue"

 

matches = pat.match(str)

 

puts matches[1] # "color"

puts matches[2] # "blue"

Сопоставление с числами, записанными римскими цифрами

Следующее довольно сложное регулярное выражение сопоставляется с любым правильно записанным римскими цифрами числом (до 3999 включительно). Как и раньше, для удобства восприятия образец разбит на части:



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 запоминает флаги для каждого выражения; тем самым флаг всего выражения перекрывается.





sdamzavas.net - 2019 год. Все права принадлежат их авторам! В случае нарушение авторского права, обращайтесь по форме обратной связи...