跳过javascript正则表达式中前面的html实体

Skip preceding html entities in javascript regex

本文关键字:html 实体 前面 javascript 正则表达式 跳过      更新时间:2023-09-26

我使用正则表达式片段将微笑符号解析为图像,但遇到了分号问题。例如,类似微笑的;)变成WINK图标,与匹配

/;-?')/g

并且在大多数情况下有效。但是像")这样的文本也与"WINK"匹配,因为引号实际上是一个html实体(" => &quotWINK)。

我尝试在正则表达式前面加上贪婪的非捕获匹配,以丢弃实体中的分号:

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

但是生成的模式仍然与"中应该跳过的分号匹配,因为它会回溯以满足非可选的后一部分。我还意识到其他合法的匹配仍然会有问题,比如EVIL:>:) => >:)

因此,我真正需要的似乎是前面缺少分号的html实体的否定

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

但它仍然匹配,我不知道为什么。

理想的情况是仍然可以得到退回的比赛,可以在没有进一步检查的情况下批量更换,但我愿意接受建议。不合适的是首先解析出html实体,因为有时它们是必要的和/或合法笑脸的一部分(就像EVIL一样)。


编辑(一些谷歌食品):

我发现(Bryan也在下文中指出)零宽度正向后看(?<!regex)将按需工作(而不是零宽度负向前看(?!regex))。

根据regular-expressions.info,后者"只有在前瞻性中的正则表达式不匹配时才会成功",这听起来不错,但当该部分是可选的时就不是了。

相比之下,前者"如果前瞻内的模式可以在某个位置匹配,则在该位置匹配",这一点并不清楚,但确实有效。因为匹配使用的是lookbacking,所以不可能通过回溯来满足正则表达式的后一部分。

因此,完整的正则表达式看起来像:

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

并且匹配这些:;) => WINK blah;) => blahWINK &quot;;) => &quot;WINK,而不匹配:&quot;)然而,它仍然与&amp;quot;) => &amp;quotWINK匹配,因此进行更多的调整将是理想的(例如,如果不导致其他带有实体的微笑符断开,则额外匹配分号来代替"与"符号)。在聊天中输入html实体的人无论如何都不太可能出现。

无论哪种方式都"足够好"--,除非javascript不支持负查找。但是,为了其他regex实现,值得进行解释。

首先,您可以检查;-)前面的空白字符,所以这是一个更简单的选择。但是,如果您确实想在JavaScript中实现负查找——它存在于几种regex中,但不存在于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"

这里有一个例子。