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 для вас. Если у вас есть какие-либо вопросы, давайте послушаем их в комментариях.