我想将一个字符串拆分成块,每个块都在最大字符数内,比如2000,并且不会拆分一个字。
我尝试过如下操作:
text.chars.each_slice(2000).map(&:join)
但有时,单词会分开。我试过一些正则表达式:
text.scan(/.{1,2000}\b|.{1,2000}/).map(&:strip)
来自this question,但我不太了解它是如何运作的,它给了我一些不稳定的行为,有时会给出只包含句号的块。
任何指针都将非常感激。
答案 0 :(得分:1)
你可以做一个记事本风格的自动换行
只需使用每行最大字符量词范围{1,N}
构造正则表达式。
以下示例每行使用32个最大值。
https://regex101.com/r/8vAkOX/1
更新:要在该范围内添加换行符,请添加dot-all修饰符(?s)
否则,将过滤掉独立的换行符。
(?s)(?:((?>.{1,32}(?:(?<=[^\S\r\n])[^\S\r\n]?|(?=\r?\n)|$|[^\S\r\n]))|.{1,32})(?:\r?\n)?|(?:\r?\n|$))
这些块位于$1
,您可以使用$1\r\n
替换以获取显示内容
看起来包裹。
解释
(?s) # Span line breaks
(?:
# -- Words/Characters
( # (1 start)
(?> # Atomic Group - Match words with valid breaks
.{1,32} # 1-N characters
# Followed by one of 4 prioritized, non-linebreak whitespace
(?: # break types:
(?<= [^\S\r\n] ) # 1. - Behind a non-linebreak whitespace
[^\S\r\n]? # ( optionally accept an extra non-linebreak whitespace )
| (?= \r? \n ) # 2. - Ahead a linebreak
| $ # 3. - EOS
| [^\S\r\n] # 4. - Accept an extra non-linebreak whitespace
)
) # End atomic group
|
.{1,32} # No valid word breaks, just break on the N'th character
) # (1 end)
(?: \r? \n )? # Optional linebreak after Words/Characters
|
# -- Or, Linebreak
(?: \r? \n | $ ) # Stand alone linebreak or at EOS
)
答案 1 :(得分:1)
<强>代码强>
def max_groups(str, n)
arr = []
pos = 0
loop do
break arr if pos == str.size
m = str.match(/.{1,#{n}}(?=[ ]|\z)|.{,#{n-1}}[ ]/, pos)
return nil if m.nil?
arr << m[0]
pos += m[0].size
end
end
<强>实施例强>
str = "Now is the time for all good people to party"
# 12345678901234567890123456789012345678901234
# 0 1 2 3 4
max_groups(str, 5)
#=> nil
max_groups(str, 6)
#=> ["Now is", " the ", "time ", "for ", "all ", "good ", "people", " to
max_groups(str, 10)
#=> ["Now is the", " time for ", "all good ", "people to ", "party"]
max_groups(str, 14)
#=> ["Now is the ", "time for all ", "good people to", " party"]
max_groups(str, 15)
#=> ["Now is the time", " for all good ", "people to party"]
max_groups(str, 29)
#=> ["Now is the time for all good ", "people to party"]
max_groups(str, 43)
#=> ["Now is the time for all good people to ", "party"]
max_groups(str, 44)
#=> ["Now is the time for all good people to party"]
str = "How you do?"
# 123456789012345678
# 0 1
max_groups(str, 4)
#=> ["How ", " ", " ", "you ", "do?"]
答案 2 :(得分:0)
这对我有用(感谢@ StefanPochmann的评论):
text = "Some really long string\nwith some line breaks"
以下内容将首先删除所有空格,然后再打破字符串。
text.gsub(/\s+/, ' ').scan(/.{1,2000}(?: |$)/).map(&:strip)
生成的字符串块将丢失原始字符串中的所有换行符(\n
)。如果您需要维护换行符,则需要使用一些随机占位符(在应用正则表达式之前)替换它们,例如:(br)
,您可以使用它来恢复换行符。像这样:
text = "Some really long string\nwith some line breaks".gsub("\n", "(br)")
运行正则表达式后,我们可以通过将(br)
的所有匹配项替换为\n
来恢复新块的换行符,如下所示:
chunks = text.gsub(/\s+/, ' ').scan(/.{1,2000}(?: |$)/).map(&:strip)
chunks.each{|chunk| chunk.gsub!('(br)', "\n")}
看起来像一个漫长的过程,但它对我有用。