【问题标题】:Javascript Regexp - Match string pattern except if string is inside specified tagJavascript Regexp - 匹配字符串模式,除非字符串在指定标记内
【发布时间】:2010-09-24 05:32:18
【问题描述】:

我正在尝试替换所有出现的 ???some.text.and.dots???在一个 html 页面上添加一个链接。我已经构建了这个正则表达式:

\?\?\?([a-z0-9.]*)\?\?\?

但是,我想排除链接内的任何结果:“ ... MY PATTERN ... ”,我对如何做有点困惑那个,我现在所有的尝试都失败了。

【问题讨论】:

    标签: javascript regex


    【解决方案1】:

    目前还不清楚您正在处理哪种“HTML”。如果是 HTML code,可能来自 Ajax 请求,那么您可以使用正则表达式;匹配链接模式,然后在回调中计算出要做什么:

    var html = document.body.innerHTML;
    html = html.replace(/(<a\s.*?>.*?<\/a>)|(\?\?\?([a-z0-9.]*)\?\?\?)/g, 
        function ( a, b, c, d ) {
           return ( a[0] == '<' ) ? a : '<a href="#">' + d + '</a>'; 
        });
    context.innerHTML = html;
    

    方便地,replace()can take a callback function 作为替换生成器而不是简单的字符串。

    但是,如果您正在处理实时 DOM 树,您可能希望尊重节点上的事件,而不是简单地重置 innerHTML。你需要一些更原始的方法:

    // returns all childnodes of type text that do not have A as parent
    function walker ( node ) {
      var nodes = [];
      for (var c, i = 0; c = node.childNodes[i]; i++) {
        if ( c.nodeType === 1 && c.tagName !== 'A' ) {
          nodes = nodes.concat( arguments.callee( c ) );
        }
        else if ( c.nodeType === 3 ) { 
          nodes.push( c );
        }
      }
      return nodes;
    }
    
    var textNodes = walker( document.body );
    for (var i = 0; i < textNodes.length; i++) {
      // create an array of strings separating the pattern
      var m = textNodes[i].nodeValue.split( /(\?\?\?([a-z0-9.]*)\?\?\?)/ );
      if ( m.length > 1 ) {
        for (var j=0; j<m.length; j++) {
          var t, parent = textNodes[i].parentNode;
          // create a link for any occurence of the pattern
          if ( /^\?\?\?([a-z0-9.]*)\?\?\?$/.test( m[j] ) ) {
            var a = document.createElement( 'a' );
            a.href = "#";
            a.innerHTML = RegExp.$1;  // m[j] if you don't want to crop the ???'s
            parent.insertBefore( a, textNodes[i] );
            t = document.createTextNode( ' ' ); // whitespace padding
          }
          else {
            t = document.createTextNode( m[j] );
          }
          parent.insertBefore( t, textNodes[i] );
        }
        // remove original text node
        parent.removeChild( textNodes[i] );
      }
    }
    

    这个方法只接触文本节点,然后只接触那些匹配模式的节点。

    【讨论】:

    • 非常详细。感人的。 +1
    • 好吧,我试图使用正则表达式后视功能,但不知道它不受 javascript 支持。但是,您的功能非常适合我的目的。谢谢!
    【解决方案2】:

    JavaScript 本身并不支持look-behind。为此,您需要运行 .match() ,然后对于每个匹配项,您需要对标签进行匹配(例如 // 紧接在前面你的比赛,然后在比赛之后)。

    祝你好运!

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-09
    • 1970-01-01
    相关资源
    最近更新 更多