【发布时间】:2020-06-15 00:30:09
【问题描述】:
有没有一种简单的方法可以在给定最大上限的情况下将一行文本拆分为一系列较短的行而不拆分单词,除非单词本身比该上限长?
【问题讨论】:
有没有一种简单的方法可以在给定最大上限的情况下将一行文本拆分为一系列较短的行而不拆分单词,除非单词本身比该上限长?
【问题讨论】:
您可以匹配以下正则表达式,它将行长限制为 40 个字符。每个匹配都是一个最大长度的非空行,以非空白字符开始和结束,包含不超过 40 个字符并且不破坏给定字符串中非空白字符的子字符串,除非这样的子字符串包含超过40 个非空白字符,在这种情况下,它会在第 40 个字符之后断开。
\S{40}| *\r?\n|\S.{0,38}\S(?!\S)
对于字符串:
All good programmers should take note and come to the aid of their company's bowling team.
Moreover, they should always be mindful that non-words, such as abcdefghiabcdefghiabcdefghiabcdefghiabcdefg may need to be split.
Also, blank lines are to be retained.
比赛如下:
1 2 3
0123456789012345678901234567890123456789
All good programmers should take note
and come to the aid of their company's
bowling team.
Moreover, they should always be mindful
that non-words, such as
abcdefghiabcdefghiabcdefghiabcdefghiabcd
efg may need to be split.
Also, blank lines are to be retained.
正则表达式为“匹配 40 个非白色字符或匹配零个或多个空格、可选的回车和换行符或匹配非空白字符后跟最多 38 个字符,后跟一个非空白字符后面没有非空白字符”。 “后面没有非空白字符”是指该字符后面跟着一个空白字符或者是该行中的最后一个字符。 (?!\S) 是一个否定的前瞻。
【讨论】:
\S{40}|(\S.{0,38}\S(?!\S))。我的版本保留了空格和行分隔符,但我更喜欢你剥离它们。 :)
\S{40}|,因为如果字符串正好有 40 个非空白字符,\S.{0,38}\S(?!\S) 也很满意。
\S{40} 会消耗最大宽度块中的单词。
这个问题很老,但考虑到正则表达式中存在 NextMatch() 方法和量化 {n,m} 特征,正则表达式解决方案似乎更清晰。以下仅在单词超过给定的最大宽度 n 时才拆分单词,否则将在最后一个空格字符处拆分行,直到并包括该行。保留空白行。模板字符串每次都以给定的宽度重建,然后逐步遍历给定的文本捕获部分行。
//F# 4.7 using .net regex
open System
open System.Text.RegularExpressions
let narrowParagraph: int -> string -> string seq = fun n s ->
let pattern = sprintf @"(?sx) \w{%d} | [^\r\n]{0,%d} (\s|\r?\n|\r)" n (n - 1)
Regex.Match(s, pattern)
|> Seq.unfold (fun (m:Match) ->
if m.Success
then Some(m.Value, m.NextMatch())
else None
)
【讨论】: