2013-06-12 17 views
8

Diciamo che ho stringhe comeSostituire un regolare submatch espressione utilizzando una funzione

input := `bla bla b:foo="hop" blablabla b:bar="hu?"` 

e voglio sostituire le parti tra virgolette in b:foo="hop" o b:bar="hu?" utilizzando una funzione.

E 'facile costruire un'espressione regolare per ottenere la partita e submatch, per esempio

r := regexp.MustCompile(`\bb:\w+="([^"]+)"`) 

e poi a chiamare ReplaceAllStringFunc ma il problema è che il callback riceve tutta la partita e non l'submatch:

fmt.Println(r.ReplaceAllStringFunc(input, func(m string) string { 
    // m is the whole match here. Damn. 
})) 

Come posso sostituire la richiesta?

In questo momento, non ho trovato una soluzione migliore di decomporre me stesso m all'interno del callback con un'espressione regolare, e per ricostruire la stringa dopo aver elaborato la submatch.

Avrei usato un approccio alternativo con un aspetto positivo dietro erano disponibili in Go ma non è il caso (e non dovrebbero essere necessari comunque).

Cosa posso fare qui?


EDIT: ecco la mia soluzione attuale che vorrei semplificare:

func complexFunc(s string) string { 
    return "dbvalue("+s+")" // this could be more complex 
} 
func main() { 
     input := `bla bla b:foo="hop" blablabla b:bar="hu?"` 
     r := regexp.MustCompile(`(\bb:\w+=")([^"]+)`) 
     fmt.Println(r.ReplaceAllStringFunc(input, func(m string) string { 
       parts := r.FindStringSubmatch(m) 
       return parts[1] + complexFunc(parts[2]) 
     })) 
} 

(playground link)

Quello che mi preoccupa è che ho per applicare l'espressione regolare due volte. Questo non suona bene.

+1

Se credi che questo è un errore di progettazione, si sentono liberi di [un bug] (http: // codice. google.com/p/go/issues/list). – fuz

+0

@FUZxxl Non so se si tratta di un errore di progettazione. Per me non sembra un design ottimale, ma potrei perdere una semplice soluzione one-pass. Se altre persone qui commentano questo, potrei presentare un bug ma ho bisogno di opinioni. –

+0

Presentare un bug se si ha una preoccupazione è quasi certamente una buona cosa. – fuz

risposta

1

Non mi piace il codice di muggito, ma sembra di fare ciò che ti sembra di volerlo fare:

package main 

import (
     "fmt" 
     "regexp" 
) 

func main() { 
     input := `bla bla b:foo="hop" blablabla b:bar="hu?"` 
     r := regexp.MustCompile(`\bb:\w+="([^"]+)"`) 
     r2 := regexp.MustCompile(`"([^"]+)"`) 
     fmt.Println(r.ReplaceAllStringFunc(input, func(m string) string { 
       return r2.ReplaceAllString(m, `"${2}whatever"`) 
     })) 
} 

Playground


uscita

bla bla b:foo="whatever" blablabla b:bar="whatever" 

MODIFICA: Take II.


package main 

import (
     "fmt" 
     "regexp" 
) 

func computedFrom(s string) string { 
     return fmt.Sprintf("computedFrom(%s)", s) 
} 

func main() { 
     input := `bla bla b:foo="hop" blablabla b:bar="hu?"` 
     r := regexp.MustCompile(`\bb:\w+="([^"]+)"`) 
     r2 := regexp.MustCompile(`"([^"]+)"`) 
     fmt.Println(r.ReplaceAllStringFunc(input, func(m string) string { 
       match := string(r2.Find([]byte(m))) 
       return r2.ReplaceAllString(m, computedFrom(match)) 
     })) 
} 

Playground


uscita:

bla bla b:foo=computedFrom("hop") blablabla b:bar=computedFrom("hu?") 
+0

Il problema è che voglio calcolare la sostituzione della submatch con una funzione complessa (prendendo questa submatch come input), ecco perché non posso semplicemente usare ReplaceAllString all'interno. Per quanto riguarda l'eleganza, temo che la soluzione giusta sia peggiore :( –

+0

@dystroy: Si prega di vedere la risposta aggiornata – zzzz

+0

+1 per una soluzione alternativa ma come la mia forza di usare due regex mentre tecnicamente la prima contiene tutto. –

Problemi correlati