Регулярное выражение, передаваемое в качестве аргумента (который я напишу в режиме «свободного пробела», чтобы сделать его самодокументированным), выглядит следующим образом:
r = /
( # start capture group 1
["'] # match a double or single parenthesis (a "character class")
) # end capture group 1
.* # match zero or more (`*`) characters (any characters)
? # make the foregoing match (.*) lazy
\1 # match the contents of capture group 1
/x # free-spacing regex definition mode
str = 'He said "Hello"'
#=> "He said \"Hello\""
str =~ r
#=> 8 (we have a match beginning at str[8])
Как str =~ r
является «правдивым», мы оцениваем
"#{$`}<<#{$&}>>#{$'}"
=> "He said <<\"Hello\">>"
Ключ в том, что в этом выражении есть три глобальные переменные:
$` #=> "He said "
$& #=> "\"Hello\""
$' #=> ""
Значения этих переменныхприведены в этом документе .Вы увидите, что:
- $ `содержит строку слева от последнего успешного совпадения;
- $ & содержит строку, сопоставленную с последним успешным совпадением;и
- $ 'содержит строку справа от последнего успешного совпадения.
Таким образом, мы имеем (и возвращаем)
"#{"He said "}<<#{"\"Hello\""}>>#{""}"
#=> => "He said <<\"Hello\">>"
Мы могли бы альтернативно использоватьметод класса Regexp :: last_match :
last_match = Regexp.last_match
#=> #<MatchData "\"Hello\"" 1:"\"">
last_match
является экземпляром класса MatchData .Этот класс содержит много полезных методов, в том числе те, которые возвращают значения трех глобальных переменных, упомянутых выше:
last_match.pre_match #=> "He said "
last_match[0] #=> "\"Hello\""
last_match.post_match #=> ""
Я не могу сказать, почему совпадение .*
в регулярном выражении было сделано lazy (делая это .*?
).