arr = str.scan(/w+/) # ['I', 'am', 'a', 'leaf', 'on', 'the',
'wind']
# Можно задать блок.
str.scan(/w+/) {|x| puts x }
Класс StringScanner
из стандартной библиотеки отличается тем, что сохраняет состояние сканирования, а не выполняет все за один раз:
require 'strscan'
str = 'Смотри, как я парю!'
ss = StringScanner.new(str)
loop do
word = ss.scan(/w+/) # Получать по одному слову.
break if word.nil?
puts word
sep = ss.scan(/W+/) # Получить следующий фрагмент,
# не являющийся словом.
break if sep.nil?
end
2.9. Форматирование строк
В Ruby, как и в языке С, для этой цели предназначен метод sprintf
. Он принимает строку и список выражений, а возвращает строку. Набор спецификаторов в форматной строке мало чем отличается от принятого в функции sprintf
(или printf
) из библиотеки С.
name = 'Боб'
age =28
str = sprintf('Привет, %s... Похоже, тебе %d лет.', name, age)
Спрашивается, зачем нужен этот метод, если можно просто интерполировать значения в строку с помощью конструкции #{expr}
? А затем, что sprintf
позволяет выполнить дополнительное форматирование - например, задать максимальную ширину поля или максимальное число цифр после запятой, добавить или подавить начальные нули, выровнять строки текста по левой или правой границе и т.д.
str = sprintf('%-20s %3d', name, age)
В классе String
есть еще метод %
, который делает почти то же самое. Он принимает одно значение или массив значений любых типов:
str = '%-20s %3d' % [name, age] # To же, что и выше
Имеются также методы ljust
, rjust
и center
; они принимают длину результирующей строки и дополняют ее до указанной длины пробелами, если это необходимо.
str = 'Моби Дик'
s1 = str.ljust(12) # 'Моби Дик'
s2 = str.center(12) # ' Моби Дик '
s3 = str.rjust(12) # ' Моби Дик'
Можно задать и второй параметр, который интерпретируется как строка заполнения (при необходимости она будет урезана):
str = 'Капитан Ахав'
s1 = str.ljust(20,'+') # 'Капитан Ахав++++++++'
s2 = str.center(20,'-') # '----Капитан Ахав----'
s3 = str.rjust(20,'123') # '12312312Капитан Ахав'
2.10. Строки в качестве объектов ввода/вывода
Помимо методов sprintf
и scanf
, есть еще один способ имитировать ввод/вывод в строку: класс StringIO
.
Из-за сходства с объектом IO
мы рассмотрим его в главе, посвященной вводу/выводу (см. раздел 10.1.24).
2.11. Управление регистром
В классе String
есть множество методов управления регистром. В этом разделе мы приведем их краткий обзор.
Метод downcase
переводит символы всей строки в нижний регистр, а метод upcase
— в верхний:
s1 = 'Бостонское чаепитие'
s2 = s1.downcase # 'бостонское чаепитие'
s3 = s2.upcase # 'БОСТОНСКОЕ ЧАЕПИТИЕ'
Метод capitalize
представляет первый символ строки в верхнем регистре, а все остальные - в нижнем:
s4 = s1.capitalize # 'Бостонское чаепитие'
s5 = s2.capitalize # 'Бостонское чаепитие'
s6 = s3.capitalize # 'Бостонское чаепитие'
Метод swapcase
изменяет регистр каждой буквы на противоположный:
s7 = 'ЭТО БЫВШИЙ попугай.'
s8 = s7.swapcase # 'это бывший ПОПУГАЙ.'
Начиная с версии 1.8, в язык Ruby включен метод casecmp
, который работает аналогично стандартному методу <=>
, но игнорирует регистр:
n1 = 'abc'.casecmp('xyz') # -1
n2 = 'abc'.casecmp('XYZ') # -1
n3 = 'ABC'.casecmp('xyz') # -1
n4 = 'ABC'.casecmp('abc') # 0
n5 = 'xyz'.casecmp('abc') # 1
У каждого из перечисленных методов имеется аналог, осуществляющий модификацию «на месте» (upcase!
, downcase!
, capitalize!
, swapcase!
).
He существует встроенных методов, позволяющих узнать регистр буквы, но это легко сделать с помощью регулярных выражений:
if string=~ /[a-z]/
puts 'строка содержит символы в нижнем регистре'
end
if string =~ /[A-Z]/
puts 'строка содержит символы в верхнем регистре'
end
if string =~ /[A-Z]/ and string =~ /а-z/
puts 'строка содержит символы в разных регистрах'