Страницы

Поиск по вопросам

четверг, 9 января 2020 г.

JavaScript и длинная регулярка

#javascript #регулярные_выражения


Доброго времени суток! У меня есть регулярка, предназначенная для поиска форм одного
и того же слова в строке. Эти регулярки автоматически генерируются для каждого слова
и получаются довольно длинными, но создаются по одному шаблону. Например нужно создать
регулярку для поиска форм слова "кот". Берём "базовую" часть регулярки: 

(^|[^0-9a-zа-я])(кот)([^0-9a-zа-я]|$)


и создаём на её основе полную регулярку для всех форм, склеивая из отдельных частей
для каждой формы: 

((^|[^0-9a-zа-я])(кот)([^0-9a-zа-я]|$)|(^|[^0-9a-zа-я])(котов)([^0-9a-zа-я]|$)|(^|[^0-9a-zа-я])(котам)([^0-9a-zа-я]|$)|(^|[^0-9a-zа-я])(котами)([^0-9a-zа-я]|$)|(^|[^0-9a-zа-я])(котах)([^0-9a-zа-я]|$)|(^|[^0-9a-zа-я])(коту)([^0-9a-zа-я]|$)|(^|[^0-9a-zа-я])(котом)([^0-9a-zа-я]|$)|(^|[^0-9a-zа-я])(коте)([^0-9a-zа-я]|$)|(^|[^0-9a-zа-я])(кота)([^0-9a-zа-я]|$)|(^|[^0-9a-zа-я])(коты)([^0-9a-zа-я]|$))


Получается такая длинная абракадабра. Возьмём некий текст, в котором встречаются
формы слова "кот": 

бла бла кот бла бла "кота" бла коты скоты


Мне нужно заменить все вхождения форм слова "кот", ограниченные не словарными символами
(пробелами, знаками препинания и тд) на ту же самую форму, обрамлённую  угловыми скобками.
То есть из исходной строки мне надо получить эту: 

бла бла <кот> бла бла "<кота>" бла <коты> скоты


Я это делаю так: 

'бла бла кот бла бла "кота" бла коты скоты'.replace(/моя большая регулярка/gi, '$1<$2>$3')


Получается вот что: 

"бла бла кот <>бла бла "кота"<> бла коты <>скоты"


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

Пробовал использовать такую замену: 

'бла бла кот бла бла "кота" бла коты скоты'.replace(/моя большая регулярка/gi, function(match)
{ return "<" + match + ">"; })


Этот вариант почти работает, выдавая такой результат: 

"бла бла< кот >бла бла <"кота"> бла< коты >скоты"


Но как можно видеть, он "захватывает" внутрь скобок кавычки и пробелы.
Подскажите, как в данной ситуации организовать корректную замену? Заранее спасибо!

Несколько важных замечаний: 


Я не могу использовать модификатор \b так как в движке регулярных выражений в JavaScript
этот модификатор корректно работает только с латинскими буквами (у меня как правило
кириллические тексты)
Примерно по той же причине я не могу пользоваться именованными группами - в Js-регулярках
они не поддерживаются 
Сами регулярки несколько упрощены в демонстрационных целях, например, в них нет буквы
"ё" и прописных букв.
Возможно тут указаны не все формы слова "кот", в данном примере это не столь важно

    


Ответы

Ответ 1



Всех своих котов сложите во вторую группу захвата console.log('бла бла кот бла бла "кота" бла коты скоты'.replace(/(^|[^0-9a-zа-яё])(кот|котов|котам|котами|котах|коту|коте|котом|кота|коты)([^0-9a-zа-яё]|$)/gi, '$1<$2>$3')); UPD для работы с котами идущими через пробел (1 символ): console.log('котам бла бла кот кот бла бла "кота"кот бла коты скоты котом'.replace(/(^|[^0-9a-zа-яё])(кот|котов|котам|котами|котах|коту|коте|котом|кота|коты)(?![0-9a-zа-яё])/gi, '$1<$2>'));

Ответ 2



Вот пример регулярки для вашего вопроса, и для примера я немного изменил пример вашей строки, и все в точности делает так как вы хотите: let str = 'бла бла кот бла &котик* sksdfk котенок бла "кота" бла коты скоты'; let res = str.replace(/([a-zа-яё]*кот[a-zа-яё]*)/gi,'<$1>'); console.log(res);

Комментариев нет:

Отправить комментарий