Ruby — один из самых популярных языков, используемых в сети. Здесь мы начали новую сессию на Nettuts +, которая познакомит вас с Ruby, а также с отличными фреймворками и инструментами, которые сопровождают разработку на Ruby. В этом уроке мы рассмотрим использование регулярных выражений в Ruby.
Предпочитаете видеоурок?
Предисловие : Синтаксис регулярного выражения
Если вы знакомы с регулярными выражениями, вы будете рады узнать, что большая часть синтаксиса для написания реальных регулярных выражений очень похожа на то, что вы знаете из PHP, JavaScript или [вашего языка здесь].
Если вы не знакомы с регулярными выражениями, попробуйте ознакомиться с нашими руководствами по регулярным выражениям здесь, в Nettuts +, чтобы освоить скорость.
Соответствие регулярному выражению
Как и все остальное в Ruby, регулярные выражения являются регулярными объектами: они являются экземплярами класса Regexp
. Однако обычно вы создаете регулярное выражение со стандартным буквальным синтаксисом:
1
2
3
|
/myregex/
/\(\d{3}\) \d{3}-\d{4}/
|
Для начала самый простой способ использовать регулярное выражение — применить его к строке и посмотреть, есть ли совпадение. И строки, и объекты регулярного выражения имеют метод match
который делает это:
1
2
3
|
«(123) 456-7890».match /\(\d{3}\) \d{3}-\d{4}/
/\(\d{3}\) \d{3}-\d{4}/.match «(123) 456-7890»
|
Оба эти примера совпадают, и поэтому мы собираемся вернуть экземпляр MatchData
(мы скоро рассмотрим объекты MatchData
). Если совпадений нет, match
вернет nil
. Поскольку объект MatchData
будет иметь значение true
, вы можете использовать метод match
в условных выражениях (например, в операторе if) и просто игнорировать получение возвращаемого значения.
Есть еще один метод, который вы можете использовать для сопоставления регулярного выражения со строками: это =~
(оператор equals-tilde). Помните, что операторы — это методы в Ruby. Как и в случае match
, этот метод возвращает nil
при отсутствии совпадения. Однако, если есть совпадение, он вернет числовую позицию строки, где началось совпадение. Также как match, и строки, и регулярные выражения имеют =~
.
1
|
«Ruby For Newbies: Regular Expressions» =~ /New/ # => 9
|
Регулярные выражения становятся более полезными, когда мы собираем некоторые данные. Обычно это делается с помощью группирования: заключая определенные части регулярного выражения в скобки. Допустим, мы хотим сопоставить имя, фамилию и род занятий в строке, где строка отформатирована следующим образом:
1
2
|
str1 = «Joe Schmo, Plumber»
str2 = «Stephen Harper, Prime Minister»
|
Чтобы получить три поля, мы создадим это регулярное выражение:
1
|
re = /(\w*)\s(\w*),\s?([\w\s]*)/
|
Это соответствует любому количеству символов слова, некоторому пробелу, любому количеству символов слова, запятой, некоторому необязательному пробелу и любому количеству символов слова или пробела. Как вы можете догадаться, части, включающие в себя символы слов, относятся к именам или профессиям, которые мы ищем, поэтому они заключены в скобки.
Итак, давайте выполним это:
1
2
|
match1 = str1.match re
match2 = str2.match re
|
Объекты MatchData
Теперь наши переменные MatchData
содержат объекты MatchData
(потому что оба наших совпадения были успешными). Итак, давайте посмотрим, как мы можем использовать один из этих объектов MatchData
.
MatchData
через это, вы заметите, что есть несколько разных способов получить те же данные из нашего объекта MatchData
. Начнем с сопоставленной строки: если вы хотите увидеть, какая исходная строка сопоставлена с регулярным выражением, используйте метод string
. Вы также можете использовать метод []
(квадратные скобки) и передать параметр 0
:
1
2
|
match1.string # => «Joe Schmo, Plumber»
match1[0] # (this is the same as match1.[] 0 ) => «Joe Schmo, Plumber»
|
Как насчет самого регулярного выражения? Вы можете найти это с помощью метода regexp
.
1
|
match1.regex # => wsw,s[ws] (this is IRB’s unique way of showing regular expressions; it will still work normally)
|
Теперь, как насчет того, чтобы получить те подходящие группы, которые были целью этого упражнения? Во-первых, мы можем получить их с нумерованными индексами на MatchData
объекте MatchData
; конечно, они в том порядке, в котором мы их сопоставили:
1
2
3
4
5
6
7
|
match1[1] # => «Joe»
match1[2] # => «Schmo»
match1[3] # => «Plumber»
match2[1] # => «Stephen»
match2[2] # => «Harper»
match2[3] # => «Prime Minister»
|
На самом деле есть еще один способ получить эти захваты: это с captures
свойств массива; так как это массив, он начинается с нуля.
1
2
3
|
match1.captures[0] # => «Joe»
match2.captures[2] # => «Prime Minister»
|
Хотите верьте, хотите нет, но на самом деле есть третий способ получить ваши снимки. Когда вы выполняете match
или =~
, Ruby заполняет ряд глобальных переменных, по одной для каждой из захваченных групп в вашем регулярном выражении:
1
2
3
4
|
«Andrew Burgess».match /(\w*)\s(\w*)/ # returns a MatchData object, but we’re ignoring that
$1 # => «Andrew»
$2 # => «Burgess»
|
Вернуться к объектам MatchData
. Если вы хотите узнать строковый индекс данного захвата, передайте номер захвата в функцию begin
(здесь вам нужен номер захвата, так как вы будете использовать его с методом []
, а не через captures
). Кроме того, вы можете использовать end
чтобы увидеть, когда заканчивается этот захват
1
2
3
4
5
6
|
m = «Nettuts+ is the best».match /(is) (the)/
m[1] # => «is»
m.begin 1 # => 8
m[2] # => «end»
m.end 2 # => 14
|
Есть также методы pre_match
и post_match
, которые довольно аккуратны: они показывают, какая часть строки была до и после совпадения соответственно.
1
2
3
|
# m from above
m.pre_match # => «Nettuts+ «
m.post_match # => » best»
|
Это в значительной степени охватывает основы работы с регулярными выражениями в Ruby.
Использование регулярных выражений
Поскольку регулярные выражения очень полезны при работе со строками, вы найдете несколько строковых методов, которые их используют. Наиболее полезными являются, вероятно, методы замещения. Это включает
-
sub
-
sub!
-
gsub
-
gsub!
Они для замены и глобальной замены, соответственно. Разница в том, что gsub
заменяет все экземпляры нашего шаблона, а sub
заменяет только первый экземпляр в строке.
Вот как мы их используем:
1
2
|
«some string».sub /string/, «message» # => «some message»
«The man in the park».gsub /the/, «a» # => «a man in a park»
|
Как вы, возможно, знаете, методы взрыва (заканчивающиеся восклицательным знаком!) Являются деструктивными методами: они изменяют реальные строковые объекты, вместо того, чтобы возвращать уже существующие. Например:
1
2
3
4
5
6
7
8
|
original = «My name is Andrew.»
new = original.sub /My name is/, «Hi, I’m»
original # => My name is Andrew.»
new # => «Hi, I’m Andrew»
original = «Who are you?»
original.sub!
original # => «And you?»
|
Помимо этих простых примеров, вы можете делать более сложные вещи, например:
1
|
«1234567890».sub /(\d{3})(\d{3})(\d{4})/, ‘(\1) \2-\3’ # => «(123) 456-7890»
|
Мы не получаем объекты MatchData
или глобальные переменные с помощью методов подстановки; однако мы можем использовать шаблон «номер обратной косой черты» в строке замены, если заключим его в одинарные кавычки. Если вы хотите дополнительно манипулировать захваченной строкой, вы можете передать блок вместо второго параметра:
1
|
«WHAT’S GOING ON?».gsub(/\S*/) {|s|
|
Есть много других функций, которые используют регулярные выражения; если вам интересно, вы должны проверить String#scan
и String#split
, для начала.
Вывод
Мы будем это регулярные выражения в Ruby для вас. Если у вас есть какие-либо вопросы, давайте послушаем их в комментариях.