Пропустить предыдущие html сущности в регулярных выражениях javascript - PullRequest
3 голосов
/ 14 июня 2011

Я использую фрагменты регулярных выражений для разбора смайликов на изображения и сталкиваюсь с проблемами с точкой с запятой. Например, смайлик как;) превращается в значок WINK, совпадающий с

/;-?\)/g

и работает в большинстве случаев. Но текст вроде ") также соответствует" WINK ", потому что кавычка на самом деле является html-сущностью (" => &quotWINK).

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

(?:"|&|<|>|'|')?

Но полученный шаблон по-прежнему совпадает с точкой с запятой в ", которую следует пропустить, поскольку он возвращает назад, чтобы удовлетворить необязательную последнюю часть. Я также понял, что все еще будут проблемы с другими законными матчами, такими как ЗЛО: >:) => >:).

Похоже, что мне действительно нужно, это отрицание предыдущих html-сущностей, пропущенных через точку с запятой:

(?!&quot|&amp|&lt|&gt|&apos|&#039)

Но он все еще совпадает, и я не уверен, почему.

Было бы идеально по-прежнему получать возвращенные спички, которые можно заменить оптом без дальнейшей проверки, но я открыт для предложений. Что не подходит, так это сначала разбор html-сущностей, потому что иногда они необходимы и / или являются частью легитимного смайлика (как в случае со ЗЛОМ).


РЕДАКТИРОВАТЬ (некоторые продукты Google):

Я обнаружил (и Брайан также отметил ниже), что положительный внешний вид с нулевой шириной, (?<!regex), будет работать по желанию (не отрицательный прогноз с нулевой шириной (?!regex)).

Как и в регулярно-expressions.info, последний «будет успешным только в том случае, если регулярное выражение в предвкушении не будет совпадать», что звучит правильно, но это не так, когда раздел необязателен.

Напротив, первый «совпадает в позиции, если шаблон внутри прогнозной точки может быть сопоставлен с окончанием в этой позиции», что не совсем понятно, но делает трюк. Поскольку при совпадении используется lookbehind, нет возможности вернуться назад, чтобы удовлетворить последнюю часть регулярного выражения.

Таким образом, полное регулярное выражение выглядит так:

/(?<!&quot|&amp|&lt|&gt|&apos|&#039);-?\)/g

и это соответствует: ;) => WINK blah;) => blahWINK &quot;;) => &quot;WINK при сбое: &quot;) Тем не менее, он по-прежнему соответствует &amp;quot;) => &amp;quotWINK, поэтому идеальным вариантом будет более тонкая настройка (например, дополнительное сопоставление точек с запятой вместо амперсандов, если это не приведет к разрыву других смайликов с объектами в них). Люди, печатающие html-сущности в чате, вряд ли придут в любом случае.

В любом случае это будет "достаточно хорошо" - , за исключением того, что javascript не поддерживает отрицательный взгляд позади . Но это стоит объяснить для других реализаций регулярных выражений.

1 Ответ

2 голосов
/ 14 июня 2011

Во-первых, вы можете просто проверить наличие пробельных символов перед ;-), так что это более простой вариант. Но если вы хотите реализовать отрицательный взгляд за в JavaScript - который существует в нескольких вариантах регулярных выражений, но не в JS - вы можете сделать что-то вроде этого:

var text = "& &amp; &amp;-) ;-) test;-)";
var ENTITIES_REGEX = /(&quot|&amp|&lt|&gt|&apos|&#039)?;-\)/g;

var result = text.replace(ENTITIES_REGEX, function(fullMatch, backref1) {
  // Ignore if there is a backreference by returning the unaltered
  // match, otherwise return WINK
  return (backref1 ? fullMatch : 'WINK');
});

// result equals "& &amp; &amp;-) WINK testWINK"

А вот пример .

...