Статьи

Рубин для новичков: регулярные выражения

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