【问题标题】:How can I word wrap a string in Perl?如何在 Perl 中对字符串进行自动换行?
【发布时间】:2023-03-30 10:29:01
【问题描述】:

我正在尝试通过 Perl 中的正则表达式创建一个松散的自动换行系统。我想要的是大约每 70 个字符左右检查下一个空格是否出现并用换行符替换该空格,然后对整个字符串执行此操作。我正在操作的字符串中可能已经有换行符,但是换行符之间的文本量往往很长。

我想避免一次循环一个字符或尽可能使用 substr,并且我更愿意编辑这个字符串而不是创建新的字符串对象。不过,这些只是偏好,如果在不破坏这些偏好的情况下无法实现我想要的东西,那也没关系。

想法?

【问题讨论】:

  • 有一个用 \b 表示的字符集代替了空格,它匹配单词边界,这可能更健壮一些。
  • @jiggy \b 不是字符类,它是零宽度断言。
  • 此外,“强调!”可能会在单词和标点符号之间中断,这是错误的!

标签: regex perl string


【解决方案1】:

查看Text::WrapText::Autoformat 等模块。

根据您的需要,甚至可以选择 GNU 核心实用程序 fold(1)。

【讨论】:

  • 这可能是最好的方法——除了一些古老的语法。
  • 其实我刚刚发现 Text::Wrap::Smart 如果有一个字长于定义的消息大小,就会停止换行。
【解决方案2】:
s/(.{70}[^\s]*)\s+/$1\n/

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

这并不能保证您的台词将严格切断为 80 个字符或其他内容。不能保证它使用的最后一个单词不会是十亿个字符。

【讨论】:

  • 我认为 .{70,80}\s+ 会更好,这样如果你得到从 71 的空格开始的“as in a”,你会得到更紧密的包裹。
  • @Axeman 是正确的,但是由于贪婪的评估(它试图匹配尽可能多的内容),你想要 .{1,70} 为 70 个字符的行长度。我已经编辑了答案来做到这一点。
  • 一个更高级的正则表达式,它可以优雅地处理换行符(而不是像上面的基本示例那样杀死它们)将是s/(.{1,70}|\S{71,})(?:\s[^\S\r\n]*|\Z)/$1\n/g。我想保持官方答案简单,所以我把它省略了。
【解决方案3】:

Welbog 的答案在 70 个字符后的第一个空格处换行。这有一个缺陷,即开始接近行尾的长词会使行过长。我建议改为在第一个(例如 81 个字符)内的最后一个空格处换行,或者如果您有一个 >80 个字符的“单词”,则在第一个空格处换行,这样只有真正牢不可破的行才会过长:

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

在现代 perl 中:

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

【讨论】:

    【解决方案4】:

    使用Text::Format,您可以获得更多的控制和可靠性

    use Text::Format;
    print Text::Format->new({columns => 70})->format($text);
    

    【讨论】:

      【解决方案5】:

      这是我一直用的。

      与公认的解决方案不同,它会在换行长度之前换行(在本例中为 70 个字符),除非有一个非常长且没有空格的“单词”(例如 URL),在这种情况下它只会放置单词单独一行,而不是打破它。

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

      第二种形式处理所有行尾:Mac \r、Unix \n、Windows \r\n 和 Teletype \n\r,但它使用哪一个作为替换仍然取决于您在替换子句中输入的内容: 我用过\n。

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

      两个版本都将第一个后的所有换行行缩进一个空格:如果您不想要,请删除最后一个 /g 之前的空格,但我通常觉得它更好。

      【讨论】:

      • 很好,但在 Perl 中应该是 $1$2 而不是 \1\2
      • @n.r.两者都可以正常工作,尽管 $ 可以避免数字字符转义的歧义。
      猜你喜欢
      • 1970-01-01
      • 2018-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-10
      • 2011-01-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多