Regex / JavaScript: разбить строку на отдельные строки по максимальному количеству символов в строке с поиском n символов назад для возможного пробела? - PullRequest
1 голос
/ 17 февраля 2020

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

Поэтому мне нужно регулярное выражение, которое разбивает строку на отдельные строки (при необходимости несколько раз) по максимуму символов в строке и оглядываясь назад n символов для возможного пробела (прервать там, если найден, в противном случае на максимальной длине)?

Редактировать 1: Например, при максимальной длине строки 30 символов и 15 символов обратного поиска пробелов:

Loremipsumissimplydummytext для отрасли печати и набора текста.

Первое слово этого предложения имеет длину 32 символа , Таким образом, выходные данные должны быть:

Loremipsumissimplydummytextoft  # Line has length of 30 char
he printing and typesetting     # Cut before the word at otherwise 30 char
industry.

Таким образом, первое слово должно быть принудительно вырезано после 30-го символа, поскольку пробелов не было.

Длина оставшейся строки равна 28 (или 29 со знаком da sh) перед словом «промышленность», поэтому на месте 30-го символа есть слово, поэтому решение ищет предыдущий пробел в диапазоне 15 символов. Эта строка прерывается перед словом «отрасль».

Редактировать 2: Второй пример текста:

Loremipsumissimply dummytext для отрасли печати и набора текста. Loremipsum - просто фальшивый текст в полиграфии и наборе текста. Loremipsumissum просто думает текст в печатной и верстки промышленности. Loremipsum - просто фиктивный текст индустрии печати и набора текста.

Должен вывести:

Loremipsumissimplydummytextoft
he printing and typesetting
industry. Loremipsumis simply
dummytext ofthe printing and
typesetting industry.
Loremipsumissimplydummytextoft
he printing and typesetting
industry. Loremipsumis simply
dummytext ofthe printing and
typesetting industry.

Сценарий использования этого регулярного выражения - форматирование длинной строки в читаемый текст с максимальной строкой принудительная длина и строки, начинающиеся с символа, а не пробела.

Необязательное требование: Когда после первоначальной публикации я добавил этот пример в Edit 1, я также добавил необязательное требование для добавление символа da sh '-' в начале следующей строки, если слово было вырезано с максимальной длиной строки. Сейчас я убираю это из примера и добавляю его как отдельное необязательное требование.

Итак, необязательное требование: если строка разбита на середине слова с максимальной длиной, а не с пробелом, тогда da sh должен быть добавлен в конце этой строки (а не в начале следующей строки, как я первоначально описал).

Loremipsumissimplydummytextoft-  # Line length 30+1 char with an appended a dash
he printing and typesetting     # Cut before the word at otherwise 30 char
industry.

Ответы [ 2 ]

1 голос
/ 17 февраля 2020

Вы можете использовать

var s = "Loremipsumissimplydummytextofthe printing and typesetting industry. Loremipsumis simply dummytext ofthe printing and typesetting industry. Loremipsumissimplydummytextofthe printing and typesetting industry. Loremipsumis simply dummytext ofthe printing and typesetting industry.";
var regex = /\s*(?:(\S{30})|([\s\S]{1,30})(?!\S))/g;
console.log(
  s.replace(regex, function($0,$1,$2) { return $1 ? $1 + "-\n" : $2 + "\n"; } )
)

Подробности

  • \s* - 0 или более пробельных символов.
  • (?: - начало группы без захвата:
    • (\S{30}) - Группа 1 (упоминается с помощью переменной $1 в методе обратного вызова): тридцать (n) непробельных символов
    • | - или
    • ([\s\S]{1,30})(?!\S)) - Группа 2 (упоминается с помощью переменной $2 в методе обратного вызова): от одного до тридцати (n) символов, как можно больше, но не сразу с непробельным символом.

Часть function($0,$1,$2) { return $1 ? $1 + "-\n" : $2 + "\n"; } означает, что если группа 1 совпадает (то есть мы сопоставляем очень длинное слово, которое сокращается на две части) мы заменяем совпадение значением 1 группы + дефис и символ новой строки. Иначе, если группа 2 совпадает, мы заменяем значение группы 2 + символ новой строки.

ES6 + фрагмент кода, совместимого с кодом :

const text = "Loremipsumissimplydummytextofthe printing and typesetting industry. Loremipsumis simply dummytext ofthe printing and typesetting industry. Loremipsumissimplydummytextofthe printing and typesetting industry. Loremipsumis simply dummytext ofthe printing and typesetting industry.";
const lineMaxLen = 30;
const wsLookup = 15; // Look backwards n characters for a whitespace
const regex = new RegExp(String.raw`\s*(?:(\S{${lineMaxLen}})|([\s\S]{${lineMaxLen - wsLookup},${lineMaxLen}})(?!\S))`, 'g');
console.log(
  text.replace(regex, (_, x, y) => x ? `${x}-\n` : `${y}\n`)
);
1 голос
/ 17 февраля 2020

Окончательный ответ:

(\ S [\ s \ S] {1,30} $ | \ S [\ s \ S] {1,29} (?: \ S +) | \ S {30})

эволюция:

  1. ([\ s \ S] {1,15} (?! \ S) | \ S {15,})

вам просто нужно изменить ответ в ссылке с помощью оператора 'или', который добавляет ваше дополнительное требование: | \ S {15,}

в ответ на ваши правки, вот мое модифицированное регулярное выражение: ([\ s \ S] {1,15} (?! \ S) | \ S {15})

вы можете замените 15 секунд на 30 или отсечение персонажа по вашему выбору

поправка для ваших дальнейших пояснений: (\ S [\ s \ S] {1,14} (?: \ S *) | \ S {15})

Теперь строка имеет начинаться с пустого пространства, и оно совпадает, но не захватывает дополнительные пробелы после первых 15 символов. Опять же, вам нужно изменить 15 и 14 на желаемую длину.

(\ S [\ s \ S] {1,30} $ | \ S [\ s \ S] {1,29} (?: \ S +) | \ S {30}) Добавление еще одного условия в множественный оператор 'or' в начале, который захватывает конец строки, если он заканчивается непробельным символом. Если он заканчивается символом пробела, вторая часть оператора 'или' захватывает его.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...