通过Regex,Ruby分割时保留模式字符

时间:2012-04-03 11:56:13

标签: ruby-on-rails ruby regex arrays string

我有以下字符串

str="HelloWorld How areYou I AmFine"

我希望这个字符串成为以下数组

["Hello","World How are","You I Am", "Fine"]

我一直在使用以下正则表达式,它正确分割,但它也省略了匹配模式,我也想保留该模式。 我得到的是

str.split(/[a-z][A-Z]/)
 => ["Hell", "orld How ar", "ou I A", "ine"] 

省略了匹配模式。

任何人都可以帮我解决如何在结果数组中保留这些字符

3 个答案:

答案 0 :(得分:6)

Ruby 1.9 中,您可以使用positive lookahead and positive lookbehind(lookahead和lookbehind正则表达式构造也称为零宽度断言)。它们匹配字符,但随后放弃匹配并仅返回结果,因此您不会丢失边框字符:

str.split /(?<=[a-z])(?=[A-Z])/
=> ["Hello", "World How are", "You I Am", "Fine"] 

Ruby 1.8 不支持lookahead / lookbehind构造。如果可能的话,我建议使用ruby 1.9。

如果您被迫使用ruby 1.8.7,我认为正则表达式对您没有帮助,我能想到的最佳解决方案是构建一个简单的状态机:迭代原始字符串中的每个字符并构建第一个字符串直到你遇到边境条件。然后构建第二个字符串等。

答案 1 :(得分:5)

到目前为止有三个答案,每个答案都有一个限制:一个是仅限rails并且在原始字符串中以下划线断开,另一个仅仅是ruby 1.9,第三个总是有一个特殊字符的潜在错误。我非常喜欢来自@Alex Kliuchnikau的零宽度断言回答,但OP需要ruby 1.8,它不支持lookbehind。有一个答案只使用零宽度前瞻,并且使用String#scan代替#split在1.8和1.9中正常工作。

str.scan /.*?[a-z](?=[A-Z]|$)/
=> ["Hello", "World How are", "You I Am", "Fine"]

答案 2 :(得分:-1)

我认为这将为你完成这项工作

str.underscore.split(/_/).each do |s| 
s.capitalize! 
end