Метод gsub
(глобальная подстановка) отличается от sub
лишь тем, что заменяются все вхождения, а не только первое:
s5 = 'alfalfa abracadabra'
s6 = s5.gsub(/a[bl]/,'xx')# 'xxfxxfa xxracadxxra'
s5.gsub!(/[lfdbr]/) { |m| m.upcase + '-' }
# s5 теперь равно 'aL-F-aL-F-a aB-R-acaD-aB-R-a'
Метод Regexp.last_match
эквивалентен действию специальной переменной $&
(она же $MATCH
).
2.14. Поиск в строке
Помимо различных способов доступа к подстрокам, есть и другие методы поиска в строке. Метод index
возвращает начальную позицию заданной подстроки, символа или регулярного выражения. Если подстрока не найдена, возвращается nil
:
str = 'Albert Einstein'
pos1 = str.index(?E) # 7
pos2 = str.index('bert') # 2
pos3 = str.index(/in/) # 8
pos4 = str.index(?W) # nil
pos5 = str.index('bart') # nil
pos6 = str.index(/Wein/) # nil
Метод rindex
начинает поиск с конца строки. Но номера позиций отсчитываются тем не менее от начала:
str = 'Albert Einstein'
pos1 = str.rindex(?E) # 7
pos2 = str.rindex('bert') # 2
pos3 = str.rindex(/in/) # 13 (найдено самое правое соответствие)
pos4 = str.rindex(?W) # nil
pos5 = str.rindex('bart') # nil
pos6 = str.rindex(/wein/) # nil
Метод include?
сообщает, встречается ли в данной строке указанная подстрока или один символ:
str1 = 'mathematics'
flag1 = str1.include? ?e # true
flag2 = str1.include? 'math' # true
str2 = 'Daylight Saving Time'
flag3 = str2.include? ?s # false
flag4 = str2.include? 'Savings' # false
Метод scan
многократно просматривает строку в поисках указанного образца. Будучи вызван внутри блока, он возвращает массив. Если образец содержит несколько (заключенных в скобки) групп, то массив окажется вложенным:
str1 = 'abracadabra'
sub1 = str1.scan(/а./)
# sub1 теперь равно ['ab','ас','ad','ab']
str2 = 'Acapulco, Mexico'
sub2 = str2.scan(/(.)(c.)/)
# sub2 теперь равно [ ['A','ca'], ['l','со'], ['i','со'] ]
Если при вызове задан блок, то метод поочередно передает этому блоку найденные значения:
str3 = 'Kobayashi'
str3.scan(/['aeiou]+[aeiou]/) do |x|
print 'Слог: #{x}
' end
Этот код выводит такой результат:
Слог: Ko
Слог: ba
Слог: уа
Слог: shi
2.15. Преобразование символов в коды ASCII и обратно
В Ruby символ представляется целым числом. Это поведение изменится в версии 2.0, а возможно и раньше. В будущем предполагается хранить символы в виде односимвольных строк.
str = 'Martin'
print str[0] # 77
Если в конец строки дописывается объект типа Fixnum
, то он предварительно преобразуется в символ:
str2 = str << 111 # 'Martino'
2.16. Явные и неявные преобразования
На первый взгляд, методы to_s
и to_str
могут вызвать недоумение. Ведь оба преобразуют объект в строковое представление, так?
Но есть и различия. Во-первых, любой объект в принципе можно как-то преобразовать в строку, поэтому почти все системные классы обладают методом to_s
. Однако метод to_str
в системных классах не реализуется никогда.
Как правило, метод to_str
применяется для объектов, очень похожих на строки, способных «замаскироваться» под строку. В общем, можете считать, что метод to_s
— это явное преобразование, а метод to_str
— неявное.
Я уже сказал, что ни в одном системном классе не определен метод to_str
(по крайней мере, мне о таких классах неизвестно). Но иногда они вызывают to_str
(если такой метод существует в соответствующем классе).
Первое, что приходит на ум, — подкласс класса String
; но на самом деле объект любого класса, производного от String
, уже является строкой, так что определять метод to_str
излишне.
А вот пример из реальной жизни. Класс Pathname
определен для удобства работы с путями в файловой системе (например, конкатенации). Но путь естественно отображается на строку (хотя и не наследует классу String
).
require 'pathname'
path = Pathname.new('/tmp/myfile')
name = path.to_s # '/tmp/myfile'
name = path.to_str # '/tmp/myfile' (Ну и что?)
# Вот где это оказывается полезно...
heading = 'Имя файла равно ' + path
puts heading# ' Имя файла равно /tmp/myfile'