Статьи

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

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