代码之家  ›  专栏  ›  技术社区  ›  Kyle Walsh

如何用Perl包装字符串?

  •  10
  • Kyle Walsh  · 技术社区  · 17 年前

    我试图通过Perl中的regex创建一个松散的单词包装系统。我想要的是大约每70个字符检查下一次出现的空格,并用换行符替换该空格,然后对整个字符串执行此操作。我操作的字符串中可能已经有新行,但新行之间的文本量往往非常长。

    我希望避免一次循环一个字符或使用SUBSTR(如果可以的话),我希望在适当的位置编辑这个字符串,而不是创建新的字符串对象。不过,这些只是偏好,如果我不能在不打破这些偏好的情况下实现我想要的目标,那就没问题了。

    思想?

    5 回复  |  直到 12 年前
        1
  •  13
  •   Welbog    17 年前
    s/(.{70}[^\s]*)\s+/$1\n/
    

    使用前70个字符,然后在下一个空白处停止,捕获过程中的所有内容。然后,发出捕获的字符串,在末尾省略空白,添加新行。

    这并不能保证你的台词会被严格地剪成80个字符或其他什么字符。不能保证它消耗的最后一个字不会有十亿个字符长。

        2
  •  23
  •   Bill Ruppert    12 年前

    看看模块 Text::Wrap 或 Text::Autoformat .

    根据您的需要,甚至GNU核心实用程序折叠(1)也可能是一个选项。

        3
  •  7
  •   ysth    13 年前

    韦尔博格的答案在70个字符后的第一个空格处。这有一个缺陷,即从靠近行尾的长单词构成了一条过长的行。我建议将最后一个空格包装在第一个空格内,例如81个字符,或者如果您有一个80个字符的“word”,则将第一个空格包装,这样只有真正不易破损的行才会过长:

    s/(.{1,79}\S|\S+)\s+/$1\n/g;
    

    现代Perl:

    s/(?:.{1,79}\S|\S+)\K\s+/\n/g;
    
        4
  •  5
  •   Bill Ruppert    12 年前

    通过使用 Text::Format

    use Text::Format;
    print Text::Format->new({columns => 70})->format($text);
    
        5
  •  1
  •   Dewi Morgan    12 年前

    这是我一直用的那个。

    与公认的解决方案不同,它将在换行长度之前换行(在本例中为75个字符),除非有一个非常长的字符串(如URL),在这种情况下,它只会将该字符串放在自己的行上,而不是将其断开。

    s/(?=.{70,})(.{0,70}\n?)( )/\1\2\n /g
    

    第二个表单处理所有行尾:mac \r、unix \n、windows \r\n和teletype \n \r,但它用作替换的行尾取决于您在replacement子句中输入了什么:我使用了\n。

    s/(?=.{70,})(.{0,70}(?:\r\n?|\n\r?)?)( )/\1\2\n /g
    

    两个版本还将第一行之后的所有包装行缩进一个空格:如果不需要,请删除最后一行/g之前的空格,但我通常会发现它更好。