我有这样的文字:
content = "Do you like to code? How I love to code! I'm always coding."
我正在尝试将其拆分为 a ?
or .
or !
:
content.split(/[?.!]/)
当我打印出结果时,缺少标点分隔符。
你喜欢编码吗
我多么喜欢编码
我一直在编码
我怎样才能保留标点符号?
我有这样的文字:
content = "Do you like to code? How I love to code! I'm always coding."
我正在尝试将其拆分为 a ?
or .
or !
:
content.split(/[?.!]/)
当我打印出结果时,缺少标点分隔符。
你喜欢编码吗
我多么喜欢编码
我一直在编码
我怎样才能保留标点符号?
回答
在括号捕获组内使用积极的后向正则表达式(即?<=
)将分隔符保留在每个字符串的末尾:
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"]
请注意,方括号捕获组不是必需的,因为只有一个分隔符。此外,由于第一个匹配发生在第一个字符处,它最终成为数组中的第一项。
要回答问题的标题,将捕获组添加到您的拆分正则表达式将保留拆分分隔符:
"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."]
不过,其他答案中给出的正则表达式确实更简洁地完成了问题的主体。
使用partition
. 文档中的一个示例:
"hello".partition("l") #=> ["he", "l", "lo"]
我会使用类似的东西:
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."]
最可靠的方法是使用自然语言处理库:Rails gem to break a paragraph into series of sentence
您还可以分组:
@content.split(/(\?+)|(\.+)|(!+)/)
分组后,可以加入句子和分隔符。
@content.split(/(\?+)|(\.+)|(!+)/).each_slice(2) {|slice| puts slice.join}