Проблема регулярного выражения Javascript с \b и международными символами

У меня много проблем с простым совпадением регулярных выражений.

У меня есть эта строка с акцентированными символами (это просто пример) "Botó Entrepà Nadó Facebook! ", и я хочу сопоставить слова, используя слова из другого списка.

Это упрощенная версия моего кода. Например, чтобы соответствовать "Botó"

var matchExpr = new RegExp ('\\b' + 'Botó' + '\\b','i'); 
"Botó Entrepà Nadó Facebook! ".match(matchExpr);

Если я запустил его, он не соответствует «Botó», как ожидалось (Firefox, IE и Chrome).

Думал ошибка на моей стороне. Но вот самое интересное...

Если я изменю строку следующим образом "Botón Entrepà Nadó Facebook! " (обратите внимание на "n" после "Botó") и запущу тот же код:

var matchExpr = new RegExp ('\\b' + 'Botó' + '\\b','i'); 
"Botón Entrepà Nadó Facebook! ".match(matchExpr);

Соответствует "Botó"!!!!????? (по крайней мере, в Firefox). Для меня это не имеет смысла, поскольку «n» НЕ является границей слова (соответствует \b).

Если вы попытаетесь сопоставить все слово:

var matchExpr = new RegExp ('\\b' + 'Botón' + '\\b','i'); 
"Botón Entrepà Nadó Facebook! ".match(matchExpr);

Оно работает.

Чтобы сделать его немного более странным, мы добавляем еще одну букву с акцентом в конце.

var matchExpr = new RegExp ('\\b' + 'Botóñ' + '\\b','i'); 
"Botóñ Entrepà Nadó Facebook! ".match(matchExpr);

Если мы попытаемся сопоставить это, оно ничему не соответствует. НО, если мы попробуем это

var matchExpr = new RegExp ('\\b' + 'Botóñ' + '\\b','i'); 
"Botóña Entrepà Nadó Facebook! ".match(matchExpr);

он соответствует "Botóñ". Что неправильно.

Если мы попытаемся сопоставить «Facebook», все будет работать, как и ожидалось. Если вы попытаетесь сопоставить слова с ударениями в середине, это сработает, как и ожидалось. Но если вы попытаетесь сопоставить слова с ударением в конце, это не удастся.

Что я делаю неправильно? Это ожидаемое поведение?


person JLP    schedule 15.03.2011    source источник


Ответы (2)


К сожалению, классы сокращенных символов в Javascript не поддерживают юникод (или даже высокий ASCII).

Взгляните на ответы на этот вопрос: Javascript + Unicode. Эта статья, связанная с этим вопросом, JavaScript, Regex и Unicode , говорит, что \b определяется границей слова, которая определяется как:

→ Символ слова — только символы A-Z, a-z, 0–9 и _.
→ Граница слова — положение между символом слова и символом, не являющимся словом.

Таким образом, это будет работать для слов с A-Z, a-z, 0-9, and _ в конце, но не для слов с диакритическими знаками в конце.

person David Fullerton    schedule 15.03.2011
comment
Значит, это будет работать для слов с ударением в конце, но не с ударением в конце. ? - person Felix Kling; 15.03.2011
comment
В Chromium, по крайней мере, .toUpperCase() и .toLowerCase() кажутся довольно удобными для юникода, поэтому c.toUpperCase() != c || c.toLowerCase() != c теоретически должно проверяться на истинность для символов, которые являются членами «алфавита с регистром» (который все еще не охватывает все границы слов.) Есть ли какой-то официальный основной список или база данных, какие глифы юникода следует считать альфой? - person Lori; 04.10.2015

Из спецификации ES3:

Внутренняя вспомогательная функция IsWordChar принимает целочисленный параметр e и выполняет следующие действия:

  1. Если e == –1 или e == InputLength, вернуть false.
  2. Пусть c будет символом Input[e].
  3. Если c является одним из шестидесяти трех символов в таблице ниже, верните true.

    a b c d e f g h i j k l m n o p q r s t u v w x y z
    A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
    0 1 2 3 4 5 6 7 8 9 _
    
  4. Вернуть ложь.

Внутренняя (возможно, гипотетическая) функция "IsWordChar()" является основой поведения утверждения "\b".

редактировать в ES5 не лучше.

person Pointy    schedule 15.03.2011