2012-05-30 49 views
1

任何人都可以向我解释这个吗?在红宝石混淆中匹配正则表达式

str = "org-id:   N/A\n" 

puts str[/org-id:\s+(.+)\n/] 
=> "org-id:   N/A\n" 
str =~ /org-id:\s+(.+)\n/ 
puts $1 
=> "N/A" 

所有我需要的是

str =~ /org-id:\s+(.+)\n/ 
puts $1 
在一行

。 但str[/org-id:\s+(.+)\n/]str.slice(/org-id:\s+(.+)\n/)返回"org-id: N/A\n"和str.scan(/ org-id:\ s +(。+)\ n /)首先返回["N/A"](和数组)。为什么所有这些比赛的表现都不一样?

回答

3

fine manual

STR [正则表达式]→new_str或零
STR [正则表达式,Fixnum对象]→new_str或零

如果Regexp被提供时,匹配部分str已退回。如果数字或名称参数遵循正则表达式,则会返回MatchData的该组件。

所以,如果你这样做str[/org-id:\s+(.+)\n/]那么你得到整个匹配部分(AKA $&);如果你想第一个捕获组(AKA $1),那么你可以说:

puts str[/org-id:\s+(.+)\n/, 1] 
# 'N/A' 

如果你有在你的正则表达式的第二捕获组,你想要什么拍摄,你可以说str[regex, 2]等。你也可以使用一个名为捕获组正是如此一个符号:

puts str[/org-id:\s+(?<want>.+)\n/, :want] 

所以用正确的方式和参数,String#[]方便拉一个基于正则表达式,块出一个字符串。

如果你看看手册,你应该注意到String#[]String#splice是一样的东西。


如果我们看一下String#=~,我们看到:

海峡=〜OBJ→Fixnum对象或零

匹配,如果OBJRegexp,用它作为与str匹配的模式,并返回比赛开始的位置,或者如果不匹配则返回nil

所以,当你说:

str =~ /org-id:\s+(.+)\n/ 

$&得到'org-id: N/A',在$1'N/A',和运营商的返回值是数字0;如果在你的正则表达式中有另一个捕获组,你会在$2中看到该部分。的=~的“nil或不nil”返回值可以让你说这样的话:

make_pancakes_for($1) if(str =~ /some pattern that makes (us) happy/) 

所以=~方便一气呵成结合解析和布尔测试。


String#scan方法:

扫描(图案)→阵列
扫描(图案){|匹配,... |块}→STR

两种形式遍历STR,匹配图案(其可以是一个RegexpString)。对于每个匹配,都会生成结果并将其添加到结果数组或传递给块。如果模式不包含组,则每个单独的结果由匹配的字符串$&组成。如果模式包含组,每个单独的结果本身就是一个数组,每个组包含一个条目。

所以scan给你匹配一个简单的列表或匹配的AoA如果捕获集团参与和scan是为了拉开一个字符串转换为它的所有组成部件一气呵成(有点像一个更复杂的版本的String#split)。

如果你想抓住所有从你的字符串(.+)比赛你会使用scanmap

array_of_ids = str.scan(/org-id:\s+(.+)\n/).map(&:first) 

但你只与麻烦,如果你知道会有几个组织的IDS在str。扫描也将离开$&,$1,...设置为scan中最后一场比赛的值;但如果您使用的是scan,那么您将一次寻找几个匹配项,以便这些全局变量不会非常有用。


三个正则表达式的方法([]=~scan)提供类似的功能,但他们填写不同的利基。你可以用scan做到这一点,但这将是毫无意义的繁琐,除非你是一个正交偏执者,然后你肯定不会在Ruby中工作,除非在极端的胁迫下,所以这并不重要。

0

这是一场比赛和一次比赛的区别。 Str [regex]返回匹配整个正则表达式的整个片段。 $ 1仅代表第一个()子句捕获的匹配部分。