正则表达式不匹配部分序列,但匹配完整序列

nat*_*ill 14 javascript regex

我有一些像这样的转义HTML:

<img border='0' />
Run Code Online (Sandbox Code Playgroud)

我正在尝试匹配和替换完整的转义序列,'但不是部分的,比如39,因为39实际上并不是未转义的字符串.实质上,每个转义序列应该被视为一个令牌.

这是一个JS正则表达式.有没有一种方法来排除之间的匹配&,并;同时还接受包括这两个字符序列?

期望的结果:

  • 搜索<img border='0' />lt:不匹配.
  • 搜索<img border='0' />39:不匹配.
  • 搜索<img border='0' />':匹配.
  • 搜索<img border='0' />border=':匹配.

当前代码:

> var str = '<img border='0' />'
> str.replace(/(border)/gi, '|$1|')
'<img |border|='0' />'  // ok
> str.replace(/(39)/gi, '|$1|')
'<img border=&#0|39|;0&#0|39|; />'  // not ok
Run Code Online (Sandbox Code Playgroud)

注意:我不能无意中重新逃脱以匹配.它必须逃脱.

Tom*_*aas 3

OP 希望 JavaScript 正则表达式能够匹配并替换转义 HTML 中的字符串,同时将转义序列(例如<')视为单个字符,并且在替换过程中不会取消转义 HTML 字符串。

这意味着替换

  1. "lt"with "[lt]"in"< lt"会导致"< [lt]"(避免实体内匹配)
  2. "<"with "[<]"in"< lt"会导致"[<] lt"(匹配实体)
  3. "&l"with "[&l]"in"< &lt"会导致"< [&l]t"(不匹配部分实体)
  4. "t;"with "[t;]"in"< lt;"会导致"< l[t;]"(不匹配部分实体)
  5. "< l"with "[< l]"in"< lt"会导致"[< l]t"(包括实体的匹配)
  6. "lt; &l"with "[lt; &l]"in"< &lt"会导致"< &lt"(不匹配部分实体)
  7. "t; <"with "[t; <]"in"lt; <"会导致"l[t; <]"(包括实体的匹配)
  8. "t; &lt"with "[t; &lt]"in"lt; <"会导致"lt; <"(不匹配部分实体)

使用以下正则表达式捕获转义序列(例如<'),

/&[a-z]+;|&#x[a-f\d]+;|&#\d+;/gi
Run Code Online (Sandbox Code Playgroud)

我们可以使用以下函数作为处理上述大多数情况的起点(#1、#2、#4、#5 和 #7):

function searchAndReplace(searchFor, replacement, str) {
  return str.replace(
    new RegExp(
      prepare(searchFor) + 
      "|(&[a-z]+;|&#x[a-f\\d]+;|&#\\d+;)", // consume entities
      "gi"
    ),
    function(m, entity) {
      return entity || replacement;
    }
  );
}

function prepare(str) {
  return str.replace(/[^\w\s]/g, "\\$&"); //escape regex metachars [1]
}

// [1] from http://eloquentjavascript.net/09_regexp.html#h_Rhu25fogrG
Run Code Online (Sandbox Code Playgroud)

其余情况(#3、#6、#8)涉及搜索字符串末尾潜在的部分转义序列。

解决方案是检查searchFor字符串末尾是否有潜在的部分转义序列,并附加相应的否定前瞻(?!)以防止匹配有效的转义序列。完整的解决方案(通过一组大约 40 个测试用例)如下所示,并且应该比方法更快且更简单.exec()

/&[a-z]+;|&#x[a-f\d]+;|&#\d+;/gi
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

1286 次

最近记录:

8 年,6 月 前