Почему выдает фрагмент слова?
Потому что разделение строки по словам - оно исключительно у вас в голове, в вашем регулярном выражении ничего про границы слов нет. Есть спецсимвол
\b
, обозначающий границы слов, но он в данном случае неприменим, поскольку у вас тут кириллические символы. Можно представить границу слова как начало строки или пробельный символ или конец строки. Типа так:
str.match(/(^|\s)[бвгджзк][аяеэюуёоиы]+[бвгджзк][а-яё]*($|\s)*?/gi).map(n => n.trim())
Но вообще - как-то не очень понятно, зачем такие сложности. Вы говорите, у вас какой-то словарь - ну так поместите слова в массив, и проверяйте на точное соответствие, волноваться о границах слов будет не нужно.