【问题标题】:How to split a line without splitting words in .net如何在.net中拆分一行而不拆分单词
【发布时间】:2020-06-15 00:30:09
【问题描述】:

有没有一种简单的方法可以在给定最大上限的情况下将一行文本拆分为一系列较短的行而不拆分单词,除非单词本身比该上限长?

【问题讨论】:

    标签: .net regex f#


    【解决方案1】:

    您可以匹配以下正则表达式,它将行长限制为 40 个字符。每个匹配都是一个最大长度的非空行,以非空白字符开始和结束,包含不超过 40 个字符并且不破坏给定字符串中非空白字符的子字符串,除非这样的子字符串包含超过40 个非空白字符,在这种情况下,它会在第 40 个字符之后断开。

    \S{40}| *\r?\n|\S.{0,38}\S(?!\S)
    

    Start your engine!

    对于字符串:

    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))。我的版本保留了空格和行分隔符,但我更喜欢你剥离它们。 :)
    • 我解释了“......在给定一些最大上限的情况下将一行文本拆分为一系列较短的行,而不拆分单词,除非单词本身比该上限长?”意思是,“有没有一种简单的方法可以在给定最大上限的情况下将一行文本拆分为一系列较短的行而不拆分单词?只有在没有单词长于该上限的情况下才能这样做。 .
    • ...您的评论表明,如果有一个超过 40 个字符的单词,例如“pneumonoultramicroscopicsilicovolcanokoniosis”,您想拆分它,但我没有想到,因为您给了没有分割规则。在这里,我正在考虑英文文本,其中单词只能在音节之间拆分。顺便说一句,这似乎是唯一一个超过 40 个字母的英文单词。 (它有 46 个。)旁注:我不明白为什么你的评论中的正则表达式中有 \S{40}|,因为如果字符串正好有 40 个非空白字符,\S.{0,38}\S(?!\S) 也很满意。
    • 不需要英语音节分割。单词的概念仅仅是非空白字符序列。该要求也是无损的。您的解决方案会跳过长度超过最大宽度的单词并去除中断的空白字符,包括其中的换行符。尽管如此,我喜欢空格剥离,但单词跳过是一个问题,因此\S{40} 会消耗最大宽度块中的单词。
    • 我明白了(终于)。我会考虑如何处理换行符。建议?
    【解决方案2】:

    这个问题很老,但考虑到正则表达式中存在 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
        )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-04
      • 1970-01-01
      • 2015-06-12
      • 2013-06-18
      • 1970-01-01
      相关资源
      最近更新 更多