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

Nad*_*sin 9 ruby regex arrays string ruby-on-rails

我有以下字符串

str="HelloWorld How areYou I AmFine"
Run Code Online (Sandbox Code Playgroud)

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

["Hello","World How are","You I Am", "Fine"]
Run Code Online (Sandbox Code Playgroud)

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

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

它省略了匹配模式.

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

Ali*_*kau 6

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

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

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

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


dbe*_*hur 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"]
Run Code Online (Sandbox Code Playgroud)

  • 扫描前瞻+1 - 您的解决方案比我的解决方案更安全,更快,更短,更好.:) (3认同)