问题 模式匹配时=〜和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()

执行时间差


9395
2018-01-15 18:07


起源

我为什么要投票? - DoLoveSky
这俩 operator 和 method 也许是在做同样的事情,但是它们的功能太过不同了 - 这些帖子都带有太多的信息,而且对于所有SO用户而言,这些信息非常棒且有用,知识渊博。尽管如此,我对投票的影响对我来说真的很糟糕!我没想到这个来自论坛。 - DoLoveSky
我没有向你投票,但我认为这是因为所写的问题是中等无意义的。您发现有多个方法可以执行类似的操作,但每个方法都会返回不同的结果。为什么这很有趣? Ruby(和大多数编程语言)中有许多方法可以执行类似的操作但返回不同的结果。 - Phrogz
@Phrogz如果OP期望他们做同样的事情会很有意思(例如, String#== 和 String#eql?)。答案当然可以通过更多的研究找到,但这是一个公平的初学者的问题。 - iamnotmaynard
问题不在于它是否有趣(这是主观的),而是方法之间的差异。 - iamnotmaynard


答案:


首先确保您使用的是正确的运算符: =~ 是正确的, ~= 不是。

运营商 =~ 返回第一个匹配的索引(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) 更多细节。


7
2018-01-15 18:21



+1 对你而言!你的发现是完美的,明白了!但我仍然对此感到困惑 hash 你要说的是什么!你可以用代码或其他东西来解释 - 这样你的想法就可以被我看到了!请 - DoLoveSky
@DoLoveSky使用irb编辑了一些输出。 - iamnotmaynard
@DoLoveSky我强烈建议您阅读我的答案中引用的ruby文档。那里有更多的信息可能非常有用。 - iamnotmaynard
是的先生:)我现在正在这样做。我只是喜欢我帖子中的两个答案! - DoLoveSky
奇怪为什么我被投了票? - DoLoveSky


当你有一个不修改状态的方法时,重要的是返回值。那么除了颜色之外,红色和蓝色之间的区别是什么?我的观点是,这是一个奇怪的问题,你似乎已经知道了答案。 (@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'

3
2018-01-15 18:22



+1 给你!很好的解释。你提供给我的很多信息。非常感谢你! - DoLoveSky
单独第一段+1。 (剩下的也很好。:) - Phrogz
重要的不仅仅是回报价值。还有一件事:速度。原则上可能(尽管事实并非如此) match 进行更广泛的计算 =~ 所以这可能是决定使用哪个因素的一个因素。这不是一个奇怪的问题。我认为你的红色与蓝色的论点没有任何意义。 - sawa
@sawa我想这实际上是一个不错的观点! - Alex Wayne
有兴趣的人我做了一个非常简单的基准测试 =~ VS match,发现 =~ 差不多快了两倍 match: pastie.org/5690542 - Casper