3 Stimmen

Javascript Regexp - Match String-Muster, außer wenn String ist innerhalb der angegebenen Tag

Ich versuche, alle Vorkommen von ???some.text.and.dots??? in einer HTML-Seite zu ersetzen, um einen Link hinzuzufügen. Ich habe diese Regexp gebaut, die es tut:

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

Ich möchte jedoch alle Ergebnisse ausschließen, die sich innerhalb eines Links befinden: "<a ...> ... MY PATTERN ... </a>", und ich weiß nicht so recht, wie ich das anstellen soll, denn alle meine Versuche sind bisher gescheitert.

9voto

Borgar Punkte 35923

Es ist nicht ganz klar, mit welcher Art von "HTML" Sie arbeiten. Wenn es HTML ist Code etwas von einer Ajax-Anfrage vielleicht, dann können Sie einen regulären Ausdruck verwenden, der sowohl einen Link ou das Muster, und arbeiten dann aus, was in einem Rückruf zu tun ist:

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;

Praktisch, replace() kann eine Rückruffunktion annehmen als Ersatzgenerator und nicht als einfache Zeichenkette.

Wenn Sie jedoch an einem lebenden DOM-Baum arbeiten, möchten Sie vielleicht Ereignisse auf Knoten respektieren und nicht einfach die innerHTML . Dafür brauchen Sie einen etwas primitiveren Ansatz:

// 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] );
  }
}

Diese Methode berührt nur Textknoten, und auch nur solche, die dem Muster entsprechen.

0voto

Rob Punkte 2996

JavaScript unterstützt von Haus aus kein Look-Behind. Um dies zu tun, müssten Sie .match() ausführen und dann für jede Ihrer Übereinstimmungen, müssten Sie Übereinstimmungen auf Ihre Tags (wie /<a \s +.*?>/ unmittelbar vor dem Spiel und dann </a> nach dem Spiel).

Viel Glück!!

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X