Проект недели.
Ранее мы уже делали редактор текста с автозаменой. Тогда исправлением текста занималась нейросеть Яндекса, а мы лишь сделали для этого оболочку. Минус подхода в том, что какой-то механизм решает за вас, какие слова правильные, а какие нужно заменить. Давайте это исправим.
На этой неделе мы делаем орфокорректор, который будет работать по вашим правилам. Вы сами решите, что и как заменять в тексте, и сами пропишете нужные правила. И при необходимости сможете их дополнять.
Это полезно, например, для деловой переписки: менеджер пишет «Засуньте себе в... свои правки, это полная чушь, я не буду это исправлять». А алгоритм заменяет это на «Коллеги! Спасибо за конструктивную критику! Нам потребуется уточнить некоторые моменты, прежде чем мы возьмем эти замечания в работу».
Логика будет такая:
- берём код прошлого проекта;
- выкидываем из него всё, что связано с нейронкой;
- на это место закидываем свой код, который меняет слова и буквы, как нужно нам;
- проверяем результат.
Регулярные выражения
Чтобы заменить одно слово на другое, в JavaScript используют функцию replace(), в которой пишут сначала, что нужно найти, а затем — на что заменить.
Например, s = s.replace('кто', 'что'); заменит в строке слово «кто» на слово «что». Это удобно и вроде как нам подходит, но смотрите, какие есть минусы у этого подхода:
- заменяется только первое найденное слово;
- если «Кто» будет написано с большой буквы, наша функция его уже не найдёт;
- имя «Гектор» превратится в «Гечтор», а казахстанский город Актобе превратится в «Ачтобе».
Чтобы такой ерунды не происходило, используют регулярные выражения.
Регулярное выражение можно представить как маленький встроенный язык программирования, заточенный под поиск и обработку текста. У этого языка есть специальные команды, которые определяют поведение алгоритма. Эти команды встраиваются в обычный текст, и получаются регулярные выражения.Несколько примеров:
код — найдёт просто эти буквы внутри любого слова, в том числе «нашкодил».
\Bкод\B — найдёт слово «код», окружённое пробелами или в начале предложения. Маркер \b означает границу слова. И тут важное замечание: в JavaScript есть маркер \b, который обозначает границу слова на латинице и \B, который обозначает границу слова в остальных алфавитах. А, например, на Python токен \b работает на всех языках.
\B[Кк]од\B — найдёт «Код» или «код» как отдельное слово. Буквы внутри квадратных скобок он воспринимает как «или». [Кк] означает «Либо заглавная К, либо строчная к».
\B[Кк]о\W\B — найдёт «Код», «Кот», «Ком», «Кое», и так же со строчной буквы. Токен \w означает любую букву слова на латинице, а \W — на всех языках.
\B[Кк]од\w{0,3}\B — найдёт «Код», «Кода», «Коду», «Кодом», «Кодами» плюс то же самое со строчных букв. В фигурных скобках указывают число возможных повторов предыдущего знака. \w{0,3} означает «любая буква, повторённая от нуля до трёх раз».
[\w-_\.]+@([\w-]+\.)+\w{2,5} — хе-хе-хе. Эта регулярка помогает найти в тексте электронные адреса. Плюсик означает «один или больше», а скобки используются, чтобы прикрепить плюсик к набору символов. Переводится так: «Сколько-то последовательностей из букв, дефисов, подчёркиваний и точек, потом собака, потом сколько-то последовательностей из букв, дефисов и точек, потом от двух до пяти букв. Если хотите, чтобы срабатывали домены типа .apartments, придется ставить в конце десятку.
Обратите внимание: плюс в регулярках означает не «одно сложить с другим», а «то, что написано передо мной, повторить один или много раз».
Если разметка регулярных выражений вам сейчас кажется сложноватой — не печальтесь. Мы сделаем об этом отдельную статью. В реальности там всё очень легко, нужно лишь выучить несколько специальных букв.
А пока что полный список основных команд и свойств регулярных выражений можно посмотреть на Хабре или JavaScript.ru.
Регулярки в JavaScript
Чтобы JavaScript понял, что мы используем регулярные выражения вместо конкретного слова при поиске, используют две косые черты:
/регулярное выражение/флаги
Флаги — это специальные команды для выражений, которые дают им суперспособности: i — нечувствительность к регистру или g — поиск по всей строке.
Вернёмся к случаю с Гектором. Чтобы при замене «кто» на «что» не возникало таких ситуаций, добавим в функцию замены регулярное выражение:
s = s.replace(/\Bкто\B/gi, ' что ');
Вы уже знаете, что \B означает границы слова.
Флаг g означает, что мы пройдём всю строку и найдём все слова «кто», чтобы их заменить. А флаг i делает наш поиск нечувствительным к регистру — он найдёт и «Кто», и «ктО», и даже «КТО».
Теперь, когда мы это знаем, мы можем менять наш текст как угодно:
- просто менять один текст на другой:
s = s.replace(/\Bкто\B/gi, 'что');
- менять один символ на другой или на целое словосочетание
s = s.replace(/\Bя\B/gi, 'неизвестно кто');
- Делать Каждое Слово Большим:
s = s.replace(/\s[а-я]/g, u => u.toUpperCase());
Сразу оговоримся: всё это работает предельно тупо, и, если мы сказали делать замену на «что», то везде будет замена на «что» со строчной. Если мы хотим сохранить заглавные буквы, то замена будет в два шага:
s = s.replace(/\Bкто\B/g, 'что');
s = s.replace(/\BКто\B/g, 'Что');
Теперь у нас есть всё что нужно, чтобы сделать свой редактор с вежливыми автозаменами.
Готовим каркас
Чтобы было быстрее, возьмём старый код и уберём из него всё, что работало с нейрокорректором.
Страница уже готова, в ней только меняем имя скрипта.
Каркас
Почистили скрипт:
Настраиваем правила автозамены в скрипте
Первое, что нам понадобится, — переменная, чтобы хранить текст из поля ввода, который мы будем обрабатывать. Её мы поставим в самое начало скрипта:
// строковая переменная, чтобы хранить текст из поля ввода var s = '';
Теперь в обработчик нажатия вместо нейроскрипта помещаем наш код. Принцип такой: берём переменную, применяем на неё одно правило, переходим к следующему. При каждом нажатии пробела или энтера наш код пройдёт по всем правилам и заменит нужные слова и символы:
ГОТОВЫЙ СКРИПТ regexp.js
Что дальше
Возможности регулярок практически безграничны. На них работают автокорректоры, автотипографы и все те алгоритмы, которым нужно механически обработать текст по правилам.
Сейчас наш алгоритм очень простой: он не учитывает рода и числа, не понимает значений слов, а текст после него лучше перечитать, чтобы не слетели склонения и спряжения. Но всё это решаемо — достаточно просто написать много новых правил.
Подписывайтесь на наш канал, чтобы не знать предела совершенству!