2013-03-28 9 views
9

Vorrei sostituire tutte le stringhe racchiuse da - in stringhe racchiuse da ~, ma non se questa stringa è di nuovo inclusa da *.Non sostituire regex se è racchiuso da un carattere

A titolo di esempio, questa stringa ...

The -quick- *brown -f-ox* jumps. 

... dovrebbe diventare ...

The ~quick~ *brown -f-ox* jumps. 

Vediamo - è sostituito solo se è non all'interno *<here>*.

mio javascript-regex per ora (che non si assume alcuna cura se è racchiuso da * o meno):

var message = source.replace(/-(.[^-]+?)-/g, "~$1~"); 

Edit: Si noti che potrebbe essere il caso che ci sia un numero dispari di * s .

+7

Perché il downvote? – poitroae

+0

yup sono stupito, una buona domanda. – Jai

+2

Cosa succede quando c'è un numero dispari di * caratteri? Per esempio. 'Il * -quick- * brown * -f-ox * salta * .' Quali caratteri' -' dovrebbero essere sostituiti e perché? –

risposta

2

Questa è una cosa complicata da fare con le espressioni regolari. Penso che quello che avrei fatto è qualcosa di simile:

var msg = source.replace(/(-[^-]+-|\*[^*]+\*)/g, function(_, grp) { 
    return grp[0] === '-' ? grp.replace(/^-(.*)-$/, "~$1~") : grp; 
}); 

jsFiddle Demo

che cerca sia- o * gruppi, ed esegue solo la sostituzione su quelli tratteggiate. In generale, le sintassi "annidate" sono impegnative (o impossibili) con espressioni regolari. (E, naturalmente, come un commento sulle note di domanda, ci sono casi particolari — metacaratteri penzolanti — che complicano anche questo.)

+1

Esempio di lavoro: http://jsfiddle.net/Zb6BU/ - non sono sicuro del motivo per cui non si sta alzando voti, funziona esattamente come previsto! +1 –

+0

@mcpDESIGNS: Anche le altre risposte stanno funzionando :-) – Bergi

+0

@Bergi Lo vedo ora, +1 per tutti :) haha ​​ –

1

vorrei risolverlo suddividendo l'array in base a * e poi sostituendo solo quelle pari indici. Corrispondenza stelle sbilanciati è più complicato, si tratta di sapere se l'indice ultimo elemento è pari o dispari:

'The -quick- *brown -f-ox* jumps.' 
    .split('*') 
    .map(function(item, index, arr) { 
     if (index % 2) { 
      if (index < arr.length - 1) { 
       return item; // balanced 
      } 
      // not balanced 
      item = '*' + item; 
     } 
     return item.replace(/\-([^-]+)\-/, '~$1~'); 
    }) 
    .join(''); 

Demo

+0

Cosa succede se la stringa contiene un '*' che non fa parte di una coppia? per esempio. ''Il -quick- * brown -f-ox jumps.'' Se ho capito bene, in questo caso entrambi' -quick-'e' -f-'dovrebbero essere sostituiti, ma solo il' '-quick-' will. –

+0

@KenB Assumerebbe che le stelle siano ben bilanciate :) –

+0

A seconda del contesto, questa è una grande ipotesi. –

1

scoprire se un match non è racchiuso da alcuni delimitatori è un compito molto complicato - vedi anche this example. Lookaround potrebbe aiutare, ma JS supporta solo lookahead. Così abbiamo potuto riscrivere "non circondato da ~" a "seguito da un numero pari o ~", e partita su quella:

source.replace(/-([^-]+)-(?=[^~]*([^~]*~[^~]*~)*$)/g, "~$1~"); 

Ma meglio abbiniamo sia - e *, in modo da consumare nulla avvolto in * s come bene e può quindi decidere in una funzione di callback, non per sostituirlo:

source.replace(/-([^-]+)-|\*([^*]+)\*/g, function(m, hyp) { 
    if (hyp) // the first group has matched 
     return "~"+hyp+"~"; 
    // else let the match be unchanged: 
    return m; 
}); 

Questo ha il vantaggio di essere in grado di specificare meglio "allegato", ad es.aggiungendo i limiti delle parole sul "dentro", per una migliore gestione dei pattern non validi (numero dispari di * caratteri come menzionato da @Maras per esempio) - l'espressione regolare corrente prende solo le due apparizioni successive.

0

Una versione terser della risposta molto chiara di Jack.

source.split(/(\*[^*]*\*)/g).map(function(x,i){ 
return i%2?x:x.replace(/-/g,'~'); 
}).join(''); 

sembra funzionare, Cin cin.

Problemi correlati