在拆分Ruby字符串时如何保留分隔符?

时间:2013-08-06 20:12:28

标签: ruby

我的文字如下:

content = "Do you like to code? How I love to code! I'm always coding." 

我正在尝试将其拆分为?.!

content.split(/[?.!]/)

当我打印出结果时,标点符号分隔符丢失了。

  

你喜欢编码

吗?      

我喜欢编码

     

我一直在编码

如何保留标点符号?

5 个答案:

答案 0 :(得分:43)

<强>答案

在括号捕获组中使用正向lookbehind正则表达式(即?<=),以将分隔符保留在每个字符串的末尾:

content.split(/(?<=[?.!])/)

# Returns an array with:
# ["Do you like to code?", " How I love to code!", " I'm always coding."]

在第二和第三个字符串的开头留下一个空格。在捕获组之后添加零个或多个空格(\s*)的匹配项以将其排除:

content.split(/(?<=[?.!])\s*/)

# Returns an array with:
# ["Do you like to code?", "How I love to code!", "I'm always coding."]

附加说明

虽然对你的例子没有意义,但是分隔符可以从第二个开始转移到字符串的前面。这是通过积极的先行正则表达式(即?=)完成的。为了寻找这种技术的人,这里有如何做到这一点:

content.split(/(?=[?.!])/)

# Returns an array with:
# ["Do you like to code", "? How I love to code", "! I'm always coding", "."]

说明行为的一个更好的例子是:

content = "- the - quick brown - fox jumps"
content.split(/(?=-)/)

# Returns an array with:
# ["- the ", "- quick brown ", "- fox jumps"]

请注意,方括号捕获组不是必需的,因为只有一个分隔符。此外,由于第一个匹配发生在第一个字符,它最终成为数组中的第一个项目。

答案 1 :(得分:15)

要回答问题的标题,在拆分正则表达式中添加捕获组将保留拆分分隔符:

"Do you like to code? How I love to code! I'm always coding.".split /([?!.])/
  => ["Do you like to code", "?", " How I love to code", "!", " I'm always coding", "."]

从那里,重建句子非常简单(或者在问题需要时进行其他按摩):

s.split(/([?!.])/).each_slice(2).map(&:join).map(&:strip)
 => ["Do you like to code?", "How I love to code!", "I'm always coding."]

其他答案中给出的正则表达式确实更简洁地完成了问题的主体。

答案 2 :(得分:6)

我会使用类似的东西:

content.scan(/.+?[?!.]/)
# => ["Do you like to code?", " How I love to code!", " I'm always coding."]

如果您想摆脱干预空间,请使用:

content.scan(/.+?[?!.]/).map(&:lstrip)
# => ["Do you like to code?", "How I love to code!", "I'm always coding."]

答案 3 :(得分:6)

使用partition。文档中的一个例子:

"hello".partition("l")         #=> ["he", "l", "lo"]

答案 4 :(得分:2)

最强大的方法是使用自然语言处理库:Rails gem to break a paragraph into series of sentences

您也可以分组:

@content.split(/(\?+)|(\.+)|(!+)/)

分组后,您可以加入句子和分隔符。

@content.split(/(\?+)|(\.+)|(!+)/).each_slice(2) {|slice| puts slice.join}