Как в регулярном выражении расставить пробелы после знаков пунктуации?

Есть текст, например:

Слово, слово ,слово,  слово  ,  слово,слово,слово  , ,  ,   ,    ,,,слово     ;    
слово;   слово, ,   , слово,слово   ;      

Нужно c помощью регулярного выражения и замены получить текст:

Слово, слово, слово, слово, слово, слово, слово, , , , , , , слово;
слово; слово, , , слово, слово;

Т.е. до знака пунктуации не должно быть пробела, а после знака пунктуации должен быть ровно один пробел. Лишние пробелы в конце строки должны удаляться. Строки ,,,, должны преобразовываться в , , , ,

Я составил регулярное выражение в Notepad++:

(?|(?<![,; ]) +([,;]) *|([,;]) {2,}(?=[^ \n\r])|([,;])(?=[^ \n\r]))| +$

Строка замены:

(?1$1 :)

Можно ли сделать как-то изящнее и правильнее?


Ответы (3 шт):

Автор решения: ksa

Нужно c помощью регулярного выражения и замены получить текст

Предложу такой вариант...

const s = `Слово, слово ,слово,  слово  ,  слово,слово,слово  , ,  ,   ,    ,,,слово     ;    
слово;   слово, ,   , слово,слово   ;`
const r = / *(,|;) */g
console.log(s.replace(r, '$1 '))

→ Ссылка
Автор решения: Алексей Р

На тестовом примере на Notepad++ отрабатывает такой паттерн:

Поиск (начинается с пробела и содержит пробелы, а не пробельные символы \s, чтобы не реагировать, например, на перевод строки. \Z используется вместо $, чтобы не реагировать на переводы строки внутри текста):

 *([;,]?) *(?=\Z)| *([;,]) *(?!\Z)

Замена на

(?1$1:$2 )

Демо на regex101 (есть отличия синтаксиса от Notepad++)

→ Ссылка
Автор решения: Олег А.

Благодарю всех за помощь. Сделал по такому алгоритму:

  1. Убираем один и более лишних пробелов. Замена на пустоту. После применения шаблона после слова не остаётся вообще ничего, а после , или ; остаётся один пробел, если там изначально было более одного пробела.

    (?<![,;]) +
    
  2. Ищем , или ;, после которых следуют ноль, два, или более пробела. Замена на $1. Причем , и ;, которые стоят в конце строки, не затрагиваются, потому что после них пробелы не нужны. Это обеспечивается выражением (?=\S).

    ([,;])( {0}| {2,})(?=\S)
    
  3. Убираем замыкающие строку пробелы. Замена на пустоту.

     +$
    

Объединим эти три шаблона в один шаблон с помощью |:

(?<![,;]) +|([,;])( {0}| {2,})(?=\S)| +$

Замена на строку:

${1:+$1 }

(для сайта regex101.com нужно выбрать flavor PCRE2).

(?1$1 )

(для Notepad++).

Строка замены $1 не отрабатывает правильно.

В итоге для тестовой строки получаем:

Слово, слово, слово, слово, слово, слово, слово, , , , , , , слово;
слово; слово, , , слово, слово;

В конце строк пробелы удаляются. Для Notepad++ кнопка "Найти Далее" ищет только "неправильные" вхождения.

Не смог найти инструкцию по строкам замены, например, ${1:+$1 }. Буду благодарен, если кинете ссылку на описание.

→ Ссылка