Ruby Regex,只有一个捕获(非常简单!)

时间:2011-10-03 17:58:57

标签: ruby regex

我想这将是一个愚蠢的错误,但对我来说,以下返回一个只包含“M”的数组。见:

/(.)+?/.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] ]

来自字符串:     “elliotpotts@sample.com”

如果不清楚,我就会出现问题:P。非常感谢你们,感谢你们这么耐心!

4 个答案:

答案 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", "!"]

请注意,其他答案正在使用(.),如果您关心捕获组则没关系,如果不这样做则有点无意义,否则它将返回它自己的独立数组中的每个字符,就像这样:

[["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 = "elliotpotts@sample.com"
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] }

也会起作用

答案 1 :(得分: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(/(.)/­)

快乐编码

答案 2 :(得分:0)

它只返回一个角色,因为这就是你要求它匹配的全部内容。您可能希望改为使用scan

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

答案 3 :(得分: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]]