Puoi creare regex di JavaScript al volo usando le variabili stringa?

Diciamo che volevo rendere il seguente riutilizzabile:

function replace_foo(target, replacement) { return target.replace("string_to_replace",replacement); } 

Potrei fare qualcosa del genere:

 function replace_foo(target, string_to_replace, replacement) { return target.replace(string_to_replace,replacement); } 

Con le stringhe letterali questo è abbastanza facile. Ma cosa succede se voglio diventare un po ‘più complicato con la regex? Ad esempio, supponiamo di voler sostituire tutto tranne string_to_replace . Istintivamente, proverei ad estendere quanto sopra facendo qualcosa del tipo:

 function replace_foo(target, string_to_replace, replacement) { return target.replace(/^string_to_replace/,replacement); } 

Questo non sembra funzionare. La mia ipotesi è che pensa che string_to_replace sia una stringa letterale, piuttosto che una variabile che rappresenta una stringa. È ansible creare espressioni regex JavaScript al volo utilizzando variabili stringa? Qualcosa di simile sarebbe bello se ansible:

 function replace_foo(target, string_to_replace, replacement) { var regex = "/^" + string_to_replace + "/"; return target.replace(regex,replacement); } 

C’è un new RegExp(string, flags) dove i flags sono g o i . Così

 'GODzilla'.replace( new RegExp('god', 'i'), '' ) 

valuta a

 zilla 

Con le stringhe letterali questo è abbastanza facile.

Non proprio! L’esempio sostituisce solo la prima occorrenza di string_to_replace . Più comunemente si desidera sostituire tutte le occorrenze, nel qual caso è necessario convertire la stringa in una RegExp globale ( /.../g ). Puoi farlo da una stringa usando il new RegExp costruttore di new RegExp :

 new RegExp(string_to_replace, 'g') 

Il problema con questo è che tutti i caratteri speciali regex nella stringa letterale si comporteranno nei loro modi speciali invece di essere caratteri normali. Dovresti eseguire il backslash, sfuggire a loro per risolverlo. Sfortunatamente, non c’è una funzione incorporata per fare questo per te, quindi eccone uno che puoi usare:

 function escapeRegExp(s) { return s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&') } 

Si noti inoltre che quando si utilizza un RegExp in replace() , la stringa sostitutiva ora ha anche un carattere speciale, $ . Questo deve anche essere sfuggito se vuoi avere un letterale $ nel tuo testo sostitutivo!

 function escapeSubstitute(s) { return s.replace(/\$/g, '$$$$'); } 

(Quattro $ s perché è di per sé una stringa di sostituzione-argh!)

Ora puoi implementare la sostituzione globale delle stringhe con RegExp:

 function replace_foo(target, string_to_replace, replacement) { var relit= escapeRegExp(string_to_replace); var sub= escapeSubstitute(replacement); var re= new RegExp(relit, 'g'); return target.replace(re, sub); } 

Che dolore. Fortunatamente se tutto quello che vuoi fare è sostituire una stringa diritta senza parti aggiuntive di regex, c’è un modo più veloce:

 s.split(string_to_replace).join(replacement) 

…e questo è tutto. Questo è un idioma comunemente compreso.

dire che voglio sostituire tutto tranne string_to_replace

Che cosa significa, vuoi sostituire tutti i tratti di testo che non prendono parte a una partita contro la corda? Una sostituzione con ^ certamente non lo fa, perché ^ indica un token di inizio stringa, non una negazione. ^ è solo una negazione in [] gruppi di caratteri. Ci sono anche lookahead negativi (?!...) , ma ci sono problemi con questo in JScript, quindi dovresti generalmente evitarlo.

Potresti provare ad abbinare “tutto fino a” alla stringa e usare una funzione per scartare qualsiasi tratto vuoto tra stringhe corrispondenti:

 var re= new RegExp('(.*)($|'+escapeRegExp(string_to_find)+')') return target.replace(re, function(match) { return match[1]===''? match[2] : replacement+match[2]; }); 

Qui, ancora una volta, una divisione potrebbe essere più semplice:

 var parts= target.split(string_to_match); for (var i= parts.length; i-->0;) if (parts[i]!=='') parts[i]= replacement; return parts.join(string_to_match); 

Come hanno detto gli altri, usa il new RegExp(pattern, flags) per farlo. Vale la pena notare che si passerà letterali stringa in questo costruttore, quindi ogni backslash dovrà essere sfuggito. Se, ad esempio, si desidera che la propria new RegExp('\\\\') corrisponda a una barra rovesciata, è necessario pronunciare il new RegExp('\\\\') , mentre la new RegExp('\\\\') regolare letterale deve essere solo /\\/ . A seconda di come intendi usarlo, dovresti evitare di passare l’input dell’utente a tale funzione senza un’adeguata preelaborazione (caratteri speciali di escape, ecc.) Senza questo, i tuoi utenti potrebbero ottenere risultati molto inaspettati.

Si, puoi.

https://developer.mozilla.org/en/JavaScript/Guide/Regular_Expressions

 function replace_foo(target, string_to_replace, replacement) { var regex = new RegExp("^" + string_to_replace); return target.replace(regex, replacement); } 

Penso di avere un ottimo esempio per evidenziare il testo in stringa (non trova registro ma evidenziato usando il registro)

 function getHighlightedText(basicString, filterString) { if ((basicString === "") || (basicString === null) || (filterString === "") || (filterString === null)) return basicString; return basicString.replace(new RegExp(filterString.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\\\$&'), 'gi'), function(match) {return ""+match+""}); } 

http://jsfiddle.net/cdbzL/1258/

Una soluzione davvero semplice è questa:

 function replace(target, string_to_replace, replacement) { return target.split(string_to_replace).join(replacement); } 

Non c’è bisogno di Regexes

Sembra anche essere il più veloce sui browser moderni https://jsperf.com/replace-vs-split-join-vs-replaceall