Как я могу переносить слова в Perl? - PullRequest
10 голосов
/ 05 июня 2009

Я пытаюсь создать систему переноса свободных слов через регулярное выражение в Perl. Я хотел бы, чтобы каждые 70 символов или около того проверяли наличие следующего пробела и заменяли этот пробел символом новой строки, а затем делали это для всей строки. В строке, над которой я работаю, уже могут быть новые строки, но объем текста между новыми строками имеет тенденцию быть очень длинным.

Я бы хотел избежать зацикливания по одному символу за раз или использования substr, если смогу, и я бы предпочел редактировать эту строку на месте, а не создавать новые строковые объекты. Это всего лишь предпочтения, и если я не могу достичь того, что ищу, не нарушая эти предпочтения, тогда это нормально.

Мысли

Ответы [ 5 ]

23 голосов
/ 05 июня 2009

Посмотрите на модули как Текст :: Обтекание или Текст :: Автоформат .

В зависимости от ваших потребностей, даже вариант с основной утилитой GNU (1) может быть опцией.

13 голосов
/ 05 июня 2009
s/(.{70}[^\s]*)\s+/$1\n/

Поглотите первые 70 символов, затем остановитесь на следующем пробеле, захватывая все в процессе. Затем сгенерируйте захваченную строку, пропустив пробел в конце и добавив новую строку.

Это не гарантирует, что ваши строки будут обрезаны строго по 80 символов или около того. Нет гарантии, что последнее слово, которое он потребляет, не будет длиной в миллиард символов.

7 голосов
/ 05 июня 2009

Ответ Велбога переносится на первый пробел после 70 символов. Это имеет недостаток в том, что длинные слова, начинающиеся близко к концу строки, образуют слишком длинную линию. Вместо этого я бы предложил заключить в последний пробел в первом, скажем, 81 символе, или в первый пробел, если у вас есть «слово»> 80 символов, так что только действительно неразрывные строки будут слишком длинными:

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

В современном Perl:

s/(?:.{1,79}\S|\S+)\K\s+/\n/g;
5 голосов
/ 06 июня 2009

Вы можете получить намного больше контроля и надежности, используя Текст :: Формат

use Text::Format;
print Text::Format->new({columns => 70})->format($text);
1 голос
/ 08 марта 2014

Это тот, который я всегда использовал.

В отличие от принятого решения, оно будет переноситься ДО длины переноса (в данном случае 75 символов), если только нет действительно длинной строки (например, 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, если вы этого не хотите, но я обычно нахожу это лучше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...