В чем разница между = ~ и match() при сопоставлении с образцом?
Я использую Ruby 1.9.3
. Я играл с некоторыми шаблонами и нашел что-то интересное:
Пример 1:
irb(main):001:0> /hay/ =~ 'haystack'
=> 0
irb(main):003:0> /st/ =~ 'haystack'
=> 3
Пример 2:
irb(main):002:0> /hay/.match('haystack')
=> #<MatchData "hay">
irb(main):004:0> /st/.match('haystack')
=> #<MatchData "st">
=~
возвращает первое местоположение своего первого совпадения, тогда как match
возвращает шаблон. Кроме этого, есть ли разница между =~
и match()
?
Разница во времени выполнения (согласно @Casper)
irb(main):005:0> quickbm(10000000) { "foobar" =~ /foo/ }
Rehearsal ------------------------------------
8.530000 0.000000 8.530000 ( 8.528367)
--------------------------- total: 8.530000sec
user system total real
8.450000 0.000000 8.450000 ( 8.451939)
=> nil
irb(main):006:0> quickbm(10000000) { "foobar".match(/foo/) }
Rehearsal ------------------------------------
15.360000 0.000000 15.360000 ( 15.363360)
-------------------------- total: 15.360000sec
user system total real
15.240000 0.010000 15.250000 ( 15.250471)
=> nil
Ответы
Ответ 1
Сначала убедитесь, что вы используете правильный оператор: =~
правильно, ~=
нет.
Оператор =~
возвращает индекс первого совпадения (nil
если нет совпадения) и сохраняет MatchData
в глобальной переменной $~
. Именованные группы захвата назначаются хешу на $~
, и, когда RegExp
является литералом в левой части оператора, также назначаются локальным переменным с этими именами.
>> str = "Here is a string"
>> re = /(?<vowel>[aeiou])/ # Contains capture group named "vowel"
>> str =~ re
=> 1
>> $~
=> #<MatchData "e" vowel:"e">
>> $~[:vowel] # Accessible using symbol...
=> "e"
>> $~["vowel"] # ...or string
=> "e"
>> /(?<s_word>\ss\w*)/ =~ str
=> 9
>> s_word # This was assigned to a local variable
=> " string"
Метод match
возвращает сам MatchData
(опять же, nil
если нет совпадения). Именованные группы захвата в этом случае по обе стороны вызова метода назначаются хешу в возвращаемом MatchData
.
>> m = str.match re
=> #<MatchData "e" vowel:"e">
>> m[:vowel]
=> "e"
Подробнее см. Http://www.ruby-doc.org/core-1.9.3/Regexp.html (а также разделы о MatchData
и String
).
Ответ 2
Когда у вас есть метод, который не изменяет состояние, все, что имеет значение, - это возвращаемое значение. Так какая разница между красным и синим, кроме цвета? Я хочу сказать, что это какой-то странный вопрос, на который вы, кажется, уже знаете ответ. (@sawa установил меня прямо здесь)
Но при этом оба метода возвращают nil
(значение фальшивости), когда регулярное выражение не совпадает. И оба метода возвращают правдивое значение, когда оно соответствует. =~
возвращает целое число, которое представляет первый символ совпадения, и даже если это 0
, потому что 0
является правдивым в Ruby. match
возвращает объект с очень подробными данными сопоставления, что удобно, когда вы хотите получить много информации о совпадении.
=~
обычно используется в условных выражениях, когда вам все равно, если что-то соответствует:
do_stuff if "foobar" =~ /foo/
do_stuff if "foobar".match(/foo/) # same effect, but probably slower and harder to read
match
обычно используется, когда вам нужны детали о том, что соответствовало:
name = "name:bob".match(/^name:(\w+)$/)[1]
puts name #=> 'bob'