2010-08-27 5 views
1

Je tente de remplacer toutes les occurrences d'un mot, par exemple «foo» entre certaines balises HTML.Expressions régulières JavaScript: correspondance et remplacement de plusieurs occurrences dans une correspondance

<span id=foo> blah blah foo blah foo blah </span> 

Je veux remplacer toutes les occurrences de foo qui ne sont pas dans l'étiquette avec bar, de sorte que le résultat final est:

<span id=foo> blah blah bar blah bar blah </span> 

Notez que « foo » dans la balise span n'a pas été remplacé .

Je peux réussir à remplacer la première (ou dernière) occurrence de "foo" par mon expression régulière, mais pas par plusieurs instances. Est-ce une situation où je devrais abandonner et ne pas essayer d'analyser cela avec une expression régulière?

Voici l'expression régulière ce genre de travaux:

RegExp('(>[\\w\\s]*)\\bfoo\\b([\\w\\s]*<)',"ig" 

ou sans javascript syntaxe:

s/>([\w\s]*)\bfoo\b([\w\s]*<)/ 

cette syntaxe me permet de faire correspondre (ou devrait) les choses match comme

[foo] mais pas bar-foo ou barfoobar ... toute occurance de foo qui sera remplacée doit se tenir debout, elle ne peut être co obtenu dans un autre mot. Comme une note, le "bla bla" est de longueur variable, et peut être beaucoup de mots différents, pas de mots, ou une combinaison de ceux-ci.

Merci pour vos suggestions.

Répondre

0

je tentais de le faire dans le mauvais sens. Voici la solution que j'ai créée et qui semble fonctionner très bien. Il utilise deux fonctions récursives + DOM traversal + expressions régulières pour créer les nœuds texte et span appropriés.

function replaceText(element, pattern, syn_text) { 

for (var childi = 0; childi < element.childNodes.length;childi++) { 
    var child= element2.childNodes[childi]; 
    if (child.nodeType==1 && child.className!=syn_text){ //make sure we don't call function on newly created node 
     replaceText(child, pattern, syn_text); //call function on child 
    } 
    else if (child.nodeType==3){ //this is a text node, being processing with our regular expression 
     var str = child.data; 
     str = str.replace(pattern,function(s, p1,p2,p3) { 
      var parentNode = child.parentNode; 
      do_replace(s, p1,p2,p3,parentNode,pattern,syn_text); 
      parentNode.removeChild(child); //delete old child from parent node. we've replaced it with new nodes at this point 
     }); 
    } 
}} 




function do_replace(s, p1,p2,p3,parentNode,pattern,syn_text) { 
    if(p1.length>0){ //this might not be necessary 
    //create textnode 
     var text_node = document.createTextNode(p1); 
     parentNode.appendChild(text_node); 
    } 
    if(p2.length > 0){ //create a span + next_node for the highlighting code 
     spanTag = document.createElement("span"); 
     spanTag.id = "SString" + id++; 
     spanTag.className = syn_text; 
     spanTag.innerHTML = p2; 
     parentNode.appendChild(spanTag); 
    } 
    if(p3.length > 0){ 
     //test to see if p3 contains another instance of our string. 

     if(pattern.test(p3)){ //if there is a instance of our text string in the third part of the string, call function again 
      p3.replace(pattern,function(s, p1,p2,p3) { 
      //debugger; 
      do_replace(s, p1,p2,p3,parentNode,pattern); 
      return; 
      }); 
     } 
     else{ //otherwise, it's just a plain textnode, so just reinsert it. 
      var text_nodep3 = document.createTextNode(p3); 
      parentNode.appendChild(text_nodep3); 
      return; 
     } 
    } 
    else{ //does this do anything? 
     return; 
    } 
return} 

Cette fonction est appelée comme suit:

syn_highlight = "highlight_me"; //class to signify highlighting 
pattern = new RegExp('([\\w\\W]*?)\\b('+ searchTerm + '[\\w]*)\\b([\\w\\W]*)',"ig"); 
replaceText($('#BodyContent')[0],pattern,syn_highlight); 
0

Ce qui suit semble fonctionner:

var str = "foo yea foot bfoo <span id=foo> blah blah foo blah foo blah </span> foo again <span id=foo>foo again</span>\n\nthis is foo again"; 
var r = new RegExp("\\bfoo\\b","ig"); 
str = str.replace(r, "'it works'"); 
alert(str); 
+0

Merci pour la réponse. Le problème avec ceci est l'expression (c'est ce que j'utilisais *, * btw), c'est qu'il remplace le "foo" dans la balise span. J'essaie d'éviter cela en créant une expression régulière qui * ne correspond pas aux éléments des tags. – user210099

+0

Ok, mais ça ne correspond pas à id = foo, ça correspond juste à foos comme mots séparés. – Zafer

1

Si vous enregistrez les résultats de votre expression régulière comme un objet match comme celui-ci:

var regex = new RegExp('(>[\\w\\s]*)\\bfoo\\b([\\w\\s]*<)',"ig"); 
var mystring = "<span id=foo> blah blah foo blah foo blah </span>"; 
var match = regex.exec(mystring); 

Vous pouvez utiliser une autre expression régulière plus simple de prendre un autre regard à la chaîne correspondante pour trouver plusieurs occurrences de "foo". La chaîne correspondante sera en match[0].

0
str = str.replace(/(>[^<]*<)/g, function(s, p1) { 
    return p1.replace(/\bfoo\b/g, ''); 
}); 
3

Je ne sais pas si quelqu'un est mentionné auparavant, mais:

NE PAS UTILISER REGEX POUR MANIPULER HTML.

C'est un outil médiocre qui n'est pas du tout équipé pour gérer la complexité du HTML. Si vous commencez à remplacer les chaînes à l'intérieur du balisage, vous pouvez facilement vous donner non seulement du balisage cassé, mais aussi des trous d'injection HTML pouvant mener à des vulnérabilités de script intersite. Ce:

(>[\\w\\s]*) 

est ne suffit pas pour assurer HTML vous modifiez est pas dans le balisage. Il est parfaitement possible d'avoir un caractère > dans une valeur d'attribut, sans parler de toutes les autres constructions de balisage.

Si votre langage est JavaScript en cours d'exécution dans un navigateur Web, il n'y a aucune raison d'essayer, car le navigateur a déjà bien analysé votre document dans les objets Element et Text. Ne demandez pas au navigateur de re-sérialiser tous ces objets de document dans le nouveau HTML, pirater le code HTML et l'écrire à innerHTML! En plus d'être lent, cela détruira tout le contenu existant pour le remplacer par de nouveaux objets, ce qui aura pour effet secondaire de perdre toutes les informations non sérialisables comme les valeurs de champs de formulaire, les références JavaScript, les expandos et les gestionnaires d'événements.

Vous pouvez simplement parcourir tous les nœuds de texte de l'élément que vous voulez examiner pour effectuer les remplacements. Trivial exemple:

function replaceText(element, pattern, replacement) { 
    for (var childi= element.childNodes.length; childi-->0;) { 
     var child= element.childNodes[childi]; 
     if (child.nodeType==1) # Node.ELEMENT_NODE 
      replaceText(child, pattern, replacement); 
     else if (child.nodeType==3) # Node.TEXT_NODE 
      child.data= child.data.replace(pattern, replacement); 
    } 
} 

replaceText($('#foo')[0], /\bfoo\b/gi, 'bar'); 
+0

en général ce que vous dites est vrai, mais si le problème est suffisamment bien délimité (par exemple, le traitement d'une simple séquence de travées) alors regex est d'accord pour faire ce genre de chose –

+0

Merci, c'était un bon point de départ pour ma finale Solution! J'accepterais ceci comme ma réponse, mais ma solution fonctionne réellement pour les buts que j'ai définis ci-dessus. – user210099

0

Je suis confus, pourquoi ne pouvez-vous faire:

var replacement = $('#foo').html().replace(/\bfoo\b/g, ''); 
$('#foo').html(replacement); 
1

Salut je faisais un reg ex remplacer par jquery en gras tous les premiers mots de tous les tags p sur mon propre site web. Je pense que le code peut également répondre à votre requête.


<!DOCTYPE html> 
<html> 
<head> 
<title>JQ Replace foo</title> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
<style type="text/css"> 
#foo {color:#00c;} 
</style> 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> 
<script type="text/javascript"> 
$(document).ready(function(){ 
$('* #foo').each(function(){ //use star to select all elements with id=foo 
var me = $(this); 
me.html(me.text().replace(/foo/g,"bar")); // only change text 'foo' to 'bar' , not the html id=foo 
}); 
}); 
</script> 
</head> 
<body> 
<div id="foo"> blah blah foo blah foo blah </div> 
<p id="foo"> blah blah foo blah foo blah </p> 
<a id="foo"> blah blah foo blah foo blah </a> 
</body> 
</html> 

simple mais fonctionne pour moi John Guise (Nouvelle-Zélande)

Questions connexes