Регулярное выражение без обратного отслеживания зависает узел на строках с новыми строками

#javascript #regex

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

Вопрос:

Я понятия не имею, почему это зависает движок javascript, но это так. У кого-нибудь еще есть подсказка?

 function isEnglish(text) {
    const checker = /^(p{Emoji}|p{ASCII}) $/u;
    return !!checker.exec(text.replace(/\n/g, ""));
}

text = `
RT @PROMOSIGROUP: FOLL TWITTER
3K:20rb
5k:30rb
10K:50rb
Foll IG aktif WW
100F:15rb
500F:50rb
1K:100rb
Jual Akun Twitter IG
081327927525/…`

isEnglish(text);
  

Хорошо, разобрался, символ «…» заставляет механизм регулярных выражений вращаться. Кто-нибудь знает, почему это может быть?

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

1. В этом шаблоне есть обратное отслеживание, потому p{ASCII} что и p{Emoji} оба совпадают с цифрами от 0 до 9 и # и * . Альтернативы не должны совпадать в одном и том же месте. Вы могли бы просто использовать символьный класс, хотя, /^[p{Emoji}p{ASCII}] $/u

Ответ №1:

Похоже, что ваш isEnglish() тест должен возвращаться true , когда исходный текст состоит исключительно из:

  • US-символы ASCII,
  • Эмодзи (не уверен, почему это будет считаться «английским», но неважно), и
  • Пунктуация

и false в противном случае.

Я мог бы указать, что US-ASCII охватывает от U 0000 до U 007F: это включает в себя управляющие символы C0 (от U 0000 до U 001F), а также [DEL] (U 007F), ни один из которых, за исключением пробелов, не является фактическим символом.

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

 function isEnglish(s) {
 return !rxIsNonEnglishAlphabet.test(s);
}

// -------------------------------------------------------
// this regular expression matches characters that are NOT
// * Whitespace
// * US-ASCII (u 0000 through U 007F)
// * Emoji
// * Punctuation
// -------------------------------------------------------
const rxIsNonEnglishAlphabet = /[^sp{ASCII}p{Emoji}p{Punctuation}]/u;
  

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

1. Спасибо, это работает хорошо. Причина включения управляющих символов / смайликов / знаков препинания в юникоде заключается в том, что я фильтрую твиты и не хочу отбрасывать их только потому, что у них есть смайлик или перевод строки.

Ответ №2:

Оказывается, что мое регулярное выражение превращается в большую ошибку возврата, хотя для меня нет ничего очевидного, что могло бы вызвать это. Моя функция теперь выглядит совсем по-другому, чтобы заставить ее работать:

 function isEnglish(text) {
    const ascii = /p{ASCII}/ug;
    const emoji = /p{Emoji}/ug;
    const punct = /p{Punctuation}/ug;
    text = text.replace(ascii, "");
    text = text.replace(emoji, "");
    text = text.replace(punct, "");
    return text.length === 0;
}