2011-10-03 96 views
6

我想这将是一个愚蠢的错误,但对我来说,以下返回一个只包含“M”的数组。看到这个:Ruby正则表达式,只有一个捕获(非常简单!)

/(.)+?/.match("Many many characters!").captures 
=> ["M"] 

为什么不返回每个字符的数组?我一定错过了明显的东西,因为我看不出这有什么问题?

编辑:刚才意识到,我不需要+?但如果没有它,它仍然不起作用。

编辑:道歉!我将阐明:我的目标是允许用户输入正则表达式和样式以及输入文本文件,只要有匹配,文本将被一个html元素包围,样式将被应用,我不只是将字符串转换成字符,我只使用给定的正则表达式,因为它是最简单的,尽管这是我的愚蠢。如何从scan()获取捕获组或者不可能?我看到$ 1包含“!” (最后一场比赛?),而不是其他人。

编辑:天哪,这真的不是我的一天。正如injekt告诉我的那样,捕获被存储在单独的数组中。我如何从原始字符串中获取这些捕获的偏移量?我希望能够获得捕获的偏移量,然后用另一个字符串包围它。或者,这是什么gsub? (我以为只有更换了比赛,不是一个捕获组)

希望最终编辑:权,让我重新开始这个:P

所以,我有一个字符串。用户将使用配置文件输入正则表达式,然后使用与每个捕获组关联的样式。我需要能够扫描整个字符串并获取每个组匹配的开始和结束或偏移量和大小。

因此,如果用户已经配置了([\w-\.]+)@((?:[\w]+\.)+)([a-zA-Z]{2,4})(电子邮件地址),那么我应该能够得到:

[ ["elliotpotts", 0, 11], 
    ["sample.",  12, 7], 
    ["com",   19, 3] ] 

从字符串: “[email protected]

如果不是很明显,我只是有些问题:P。非常感谢你们,感谢你的耐心等待!

+0

我刚刚看到你的编辑,扫描的捕获组存储在单独的数组中,只是尝试你的正则表达式和在irb中的测试字符串,你会看到。答案仍然与您的编辑相同 –

+0

刚看到您的下一次编辑,您将不得不更新更多的信息。我现在有点困惑:P随时抛出一个更完整的例子,无论它是如何做作,所以我们确切地知道你需要提取什么 –

+0

好吧,用你最新的编辑更新我的答案。我现在有点时间了,所以这只是完整的解决方案,没有解释,让我知道如果它没有意义,我会更新它 –

回答

9

因为您的捕获只匹配一个单个字符。(.)+是不一样的(.+)

>> /(.)+?/.match("Many many characters!").captures 
=> ["M"] 
>> /(.+)?/.match("Many many characters!").captures 
=> ["Many many characters!"] 
>> /(.+?)/.match("Many many characters!").captures 
=> ["M"] 

如果你想匹配的每一个字符递归使用String#scanString#split如果你不关心的捕捉组

使用扫描:

"Many many characters!".scan(/./) 
#=> ["M", "a", "n", "y", " ", "m", "a", "n", "y", " ", "c", "h", "a", "r", "a", "c", "t", "e", "r", "s", "!"] 

注其他的答案是使用(.),如果你关心捕获组,那么这很好,如果你不这样做,这是没有意义的,否则它会返回它的每一个字符N个独立阵列,像这样:

[["M"], ["a"], ["n"], ["y"], [" "], ["m"], ["a"], ["n"], ["y"], [" "], ["c"], ["h"], ["a"], ["r"], ["a"], ["c"], ["t"], ["e"], ["r"], ["s"], ["!"]] 

否则,只需使用split"Many many characters!".split(' ')"

编辑在回答您的编辑:

reg = /([\w-\.]+)@((?:[\w]+\.)+)([a-zA-Z]{2,4})/ 
str = "[email protected]" 
str.scan(reg).flatten.map { |capture| [capture, str.index(capture), capture.size] } 
#=> [["elliotpotts", 0, 11], ["sample.", 12, 7], ["com", 19, 3]]` 

哦,你不需要扫描,你并不是真正扫描,所以你不需要遍历,至少不是你提供的例子:

str.match(reg).captures.map { |capture| [capture, str.index(capture), capture.size] } 

还将努力

+0

谢谢!我还找到了一个替代答案,现在将它发布。谢谢! – Ell

+0

给出的两个代码片段在一般情况下不适用于偏移量,它们只在匹配的子字符串全部不同时才起作用。例如,如果有3个匹配的“h”,那么相同的索引('h'的第一个实例)全部返回3次。 str.index(capture)返回捕获子字符串的FIRST实例的索引。 – jpwynn

0

它只返回一个字符,因为这是你要求它匹配的。你可能想使用scan代替:

str = "Many many characters!" 
matches = str.scan(/(.)/) 
1

是,一些重要的东西被错过;-)

(...)只介绍一个捕获组:作为指数是由正规只确定次小组赛的数量无关表达本身而不是输入。

关键是一个“全局正则表达式”,它将按顺序多次应用正则表达式。在Ruby中,这是从Regex#match反相到String#scan完成(很多其他语言有一个“/ G”正则表达式修改):

"Many many chara­cters!".sc­an(/(.)+?/­) 
# but more simply (or see answers using String#split) 
"Many many chara­cters!".sc­an(/(.)/­) 

快乐编码

0

下面的代码是从Get index of string scan results in ruby和修改我喜欢。

[].tap {|results| 
    "abab".scan(/a/) {|capture| 
     results.push(([capture, Regexp::last_match.offset(0)]).flatten) 
    } 
} 

=> [["a", 0], ["a", 2]] 
相关问题