【问题标题】:Convert recursive PHP regex to JavaScript将递归 PHP 正则表达式转换为 JavaScript
【发布时间】:2011-11-25 21:24:19
【问题描述】:

我需要帮助才能在 JavaScript 中复制这个 PHP 正则表达式:

#\<code>((?:[^<]|\<(?!/?code>)|(?R))+)\</code>#

它会去除除code 标签内的所有标签。

【问题讨论】:

  • 那将是 JavaScript - jQuery 不做正则表达式
  • 这个正则表达式当然不会像你说的那样做。 [code] 匹配单个字母,c、o、d 或 e。至少括号必须被转义。
  • 相反,您为什么不定义您想要的正则表达式的参数并向我们展示您的尝试,我们将能够为您提供帮助。

标签: php javascript regex


【解决方案1】:

这是不可能的。

您无法将此正则表达式转换为 JavaScript 风格,因为它使用了 JavaScript 正则表达式引擎不支持的递归 (?R)

我会建议一种不同的方法。我假设您要删除尖括号中的所有内容,包括周围的括号,除非在 &lt;code&gt;...&lt;/code&gt; 块中找到这些括号。对?好吧,JavaScript 正则表达式(甚至不支持后向断言)可以为您做的最好的事情是:

result = subject.replace(/<(?!\/code)[^<>]*>\s*(?!(?:(?!<code>)[\s\S])*<\/code>)/g, "");

这是做什么的(不幸的是,JavaScript 甚至也不支持冗长的正则表达式;这个正则表达式很难理解......):

<             # Match a <
(?!/code)     # (unless it's part of a </code> tag)
[^<>]*        # and any number of non-bracket characters
>             # followed by >
\s*           # and any whitespace.
(?!           # Assert that we can't match the following here:
 (?:          # The following expression:
  (?!         # Unless we are right before a
   <code>     # <code> tag
  )           # Then match
  [\s\S]      # any character
 )*           # any number of times
 </code>      # until the next </code> tag
)             # End of lookahead assertion

这确保我们只匹配一个标签,如果接下来的下一个&lt;code&gt;/&lt;/code&gt;标签是一个开始&lt;code&gt;标签,而不是一个结束&lt;/code&gt;标签(或者如果根本没有这样的标签)。

所以它变了

This <b> is bold </b> text, 
but we want <code> these <i> tags <b> here </b> to remain </i> </code> 
while those <b> can be deleted</b>.

进入

This is bold text, 
but we want <code> these <i> tags <b> here </b> to remain </i> </code> 
while those can be deleted.

如果你也想自己删除code标签,你可以使用

result = subject.replace(/<[^<>]*>\s*(?!(?:(?!<code>)[\s\S])*<\/code>)|<code>\s*/g, "");

这将给出结果

This is bold text, 
but we want these <i> tags <b> here </b> to remain </i> 
while those can be deleted.

如果code 标签可以嵌套,这些正则表达式都不起作用。

【讨论】:

  • 正则表达式错误,我更新了。是否可以通过其他方式在javascript中实现递归(?R)?
  • 你不能做递归,但如果你愿意接受我的解决方案的局限性,那是你在 JavaScript 中单独使用正则表达式的下一个最佳解决方案。不过,解析器会更防弹。
  • 1.是否可以剥离 标记并将html保留在里面? 2、万一在一个...里面找到了其他,这些不能删除吗?
  • 我不完全确定你所说的 1 是什么意思。你想保留正则表达式现在的行为并另外删除代码标签吗?大约 2.,这就是这个正则表达式失败的地方。嵌套代码标签会导致失败,因为嵌套确实需要递归。所以如果你不能保证代码标签永远不会被嵌套,你就不能在 JavaScript 中使用正则表达式。
  • 一个例子来弄清楚:
    这个是粗体文本,但是我们希望这些<i>标签<b>在这里</b>保留</i>和内码标签也是,而其他被删除
     这是粗体文本,但我们希望这些  标签  这里  也保留 inner code 标签,而其他标签则保留删除。 
    谢谢...
【解决方案2】:

如果您想在 JavaScript 中执行此操作,我猜您可能正在一个环境中工作,您手头已经拥有一套完整的 HTML 解析和遍历工具——浏览器 DOM。

如果情况确实如此,那么关于正则表达式不是处理标记的理想工具的普遍好建议在此适用,您可以考虑改用其他方法。

将给定的标记放入可以使用 DOM 界面对其进行操作的表单非常简单:

var working = document.createElement('div');  //create a new empty element
working.innerHTML = sourceToSanitize;         //put your HTML source inside it
var sanitized = sanitize(working);            //call sanitization function!

现在您只需要一个 sanitize 函数,您可以调用该元素,该函数将遍历其中的 DOM 树中的每个节点,并返回一个转换后的 HTML 片段。

这样的事情可能会奏效:

function sanitize(emt) {
    if(emt.nodeType == 3)     // terminal cond #1: just return text nodes
        return emt.textContent;
    if(emt.nodeType != 1)     // terminal cond #2: non-text/element nodes yield null
        return null;
    if(emt.tagName=='code' || emt.tagName=='CODE') //#3: code tags returned untouched
        return outerHTML(emt);

                              // recurse over all child nodes
    var schf = [], // *S*anitized *C*hild *H*TML *F*ragments
        children = emt.childNodes;
    for(var i=0,z=children.length; i<z; i++) 
        schf.push(sanitize(children[i]));
    return schf.join('');     // smoosh results together and serve fresh!
}

function outerHTML(emt) {
    if(emt.outerHTML) return emt.outerHTML;
    var tmp = document.createElement('div');
    tmp.appendChild(emt.cloneNode(true));
    return tmp.innerHTML;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-12
    • 2011-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-09
    相关资源
    最近更新 更多