2011-03-04 4 views
4

RegExp peut remplacer les modèles de correspondance avec les remplacements impliquant ce qui est connu sous le nom Tagged ExpressionsJavaScript, RegExp - remplace par une expression évaluée impliquant des expressions étiquetées?

Exemple:

var s = "... some string with full things..."; 
s = s.replace(/(some|full)/gi, "\"aw$1\"); 

qui se traduira par

'... "awsome" string with "awfull" things...' 

et la vie sont cool, parce que certains et complet sont appariés, et 1 $ dans le strin remplacé g reflète le apparié Expression étiquetée dans les accolades, dans ce cas - exactement seulement certains ou complet.

Maintenant que nous avons eu l'idée - Je cherche une idée de faire ce qui suit:

cordes avant:

"{timeOfEffect: 3*24*60*60 }" 

cordes après

"{timeOfEffect: 259200}" 

Les valeurs sont représentés comme cela parce qu'ils sont édités par des humains à des termes compréhensibles comme (60 sec * 60 min * 24 heures) * 3 => 3 jours (ne demandez pas la demande du client), mais lisez en termes informatiques lik e 259200 en secondes, et pourrait contenir de nombreuses occurrences de ce modèle. Je pensais essayer de créer une expression de remplacement qui multiplie $ 1 et $ 2, ou même passer $ 1 et $ 2 à une fonction, ou passer $ 1 * $ 2 à un contexte d'évaluation, mais je dois créer une fonction pour cela fais-le manuellement.

Le plus proche je suis arrivé est

var x = /([0-9]*)\s\*\s([0-9]*)/g 
    , r = function(m){ 
      return m[1] * m[2]; 
     } 
while (m = x.exec(s)) 
    s = s.replace(x, r(m)); 

qui suce un peu parce que exec rendements seulement le premier match. Après la manipulation dans la déclaration remplacer - la recherche suivante recommence depuis le début de la chaîne - qui est une chaîne de longueur 60K ...

Une bonne solution sera une des opérations suivantes: a) effectuer le match à partir d'un index (sans créer une nouvelle sous-chaîne pour cela) b) fournir une expression de remplacement permettant l'évaluation

L'approche alternative sera de marquer la chaîne et de la traiter en bits - ce qui est une alternative totale à RegExp qui va prendre beaucoup de code et d'effort, auquel cas je vais juste vivre avec la pénalité de performance ou donner un meilleur combat sur une meilleure alternative pour cette exigence ...

Aider quelqu'un?

Répondre

6
var s = "timeOfEffect: 3*24*60*60 var: 6*8 "; 
var r = new RegExp("([0-9*+-/]{0,}[0-9])","g"); 
s = s.replace(r,function(match){ return eval(match); }); 
alert(s) 
+0

wow. celui-ci est cool! avec un petit ajustement à la reg-exp - il couvre toutes les arithméthiques de base (en supposant qu'ils sont syntaxiquement corrects)! - Radagast the Brown il y a 0 secondes edit –

+1

Ok, voici la solution finale. Il peut facilement être étendu pour soutenir les accolades, mais je n'en ai pas besoin. Le problème avec l'offre originale était qu'elle correspondait aussi à des nombres simples - qui n'ont pas besoin d'être remplacés. 'var r = new RegExp (" ([0-9 \\.] +) ([\\ * + - \\ /].) ([0-9 \\ * + - \\ /] +) ([0-9]) "," g ");' 'r = fonction (m, m1, m2, m3, m4) {' 'try {' 'return": "+ eval (m1 + m2 + m3 + m4) '' } catch (ex) { '' retour ": \" @@ EVAL_ERROR: "+ m1 + m2 + m3 + m4 + "\"" '' } '' } '' } '' s = s.replace (x, r) ' La sortie est évidemment vérifiée contre "@@ EVAL_ERROR" et envoie des messages électroniques sur les configurations brisées ... Merci :) –

+0

Hey kewwwwwlll! le pré-dernier argument de la fonction match est l'indice de correspondance dans la chaîne recherchée, et le dernier argument est la chaîne entière recherchée elle-même !! et c'est sacrément rapide! Je peux l'utiliser pour émettre des erreurs d'analyse précises aux éditeurs !! :) –

4
var str = '{timeOfEffect: 3*24*60*60}, {timeOfEffect: 1+7}, {timeOfEffect: 20-3}, {timeOfEffect: 3/0}'; 

var result = str.replace(/\s([\d\/\*\-\+\s]+?)\}/g, function(all, match) { 
    return eval(match) + '}'; 
}); 

document.body.innerHTML = result; 
// {timeOfEffect:259200}, {timeOfEffect:8}, {timeOfEffect:17}, {timeOfEffect:Infinity} 

jsFiddle.

eval() est sûr à utiliser parce que nous avons assuré la chaîne ne contient que 0-9, , \n, \t, /, *, - et +. I was hoping il peut y avoir quelque chose comme Math.parse(), mais il n'y a pas.

Si vous avez besoin de calculs plus complexes nécessitant une parenthèse, ajoutez simplement ( et ) à la plage de caractères regex.

Questions connexes