2010-06-04 15 views
7

mi hai testo in formato follwing:regex vim per la sostituzione di spazi tra virgolette

ERR_OUT_OF_MEM, "ERR OUT OF MEM" 
ERR_SOMETHING_BAD, "ERR SOMETHING BAD" 

voglio sostituire tutti gli spazi nel testo, che sono tra virgolette con sottolineature:

ERR_OUT_OF_MEM, "ERR_OUT_OF_MEM" 
ERR_SOMETHING_BAD, "ERR_SOMETHING_BAD" 

La migliore regex ho potuto venire in mente è:

\("\w\+\)\@<= 

(c'è uno spazio alla fine di quello)

ma questo trova solo il primo spazio in ogni stringa quotata, e avrei bisogno di ripetere questo più volte per ottenere l'effetto desiderato.

Un modo per farlo in uno scatto?

Grazie!

risposta

6

V'è certamente un modello 0-length che funziona in un solo passaggio, ma come non ho mai avuto molto successo con loro, io preferisco questo tipo di approccio:

:%s/\%("[^"]*"\)*\("[^"]*"\)/\=substitute(submatch(1), ' ', '_', 'g')/g 

Nota: doppi apici sono mantenuti raggruppati 2 da 2 per non trasformare

foo bar "foo bar" "foo barr" 

in

foo bar "foo_bar"_"foo_barr" 

EDIT: come indicato o rampion ut, il seguente è più che sufficiente:

%s/"[^"]*"/\=substitute(submatch(0), ' ', '_', 'g')/g 
+0

perché non utilizzare il '/ "[^"] *"/'modello non capisco che cosa saltare le coppie iniziali di virgolette ti compra (con '\% (" [^ "] *" \) * ') – rampion

+0

Buon punto. Ero persuaso che la ricerca ricominciava non dopo la citazione di chiusura, ma dopo quella di apertura. Correggo la regex. Grazie. –

6

Questa non è una soluzione general-purpose, dal momento che corrisponderà a qualsiasi spazio che appare da nessuna parte, dopo una doppia citazione su una linea, ma dovrebbe funzionare per archi in il formato specificato:

s/\v(\".*)@<= /_/g 

ho usato il \ v (verymagic) pegno perché penso che rende l'espressione regolare un po 'più leggibile, e ho compreso l'intero sostituzione del comando, dal momento che la 'g' alla fine è importante.

Per quelli che seguono a casa, questa espressione regolare imposta innanzitutto la modalità 'moltomagica' con \ v. Quindi definisce il token (\".*) che significa "una virgola doppia e poi qualsiasi altra cosa" e usa l'asserzione lookbehind @<= per dire "corrisponde solo alle cose che seguono l'ultimo token" - in altre parole, corrisponde solo alle cose che arrivano da qualche parte dopo una doppia citazione . Infine, c'è uno spazio, che è quello che effettivamente viene abbinato, e il termine di sostituzione è un trattino basso, che è quello con cui vogliamo sostituirlo, e lo g dice "sostituisci tutti i termini corrispondenti" in modo da non ottenere solo il primo Corrispondenza trovata.

+0

Funziona, ma sostituisce anche gli spazi che ho alla fine della linea. –

+0

Ah. Sì, se hai degli spazi finali hai bisogno di un approccio più complesso. Quello di Luc, sopra, dovrebbe farlo. –

0

Il mio PatternsOnText plugin fornisce un comando :SubstituteInSearch. Con esso, in primo luogo di ricerca per le stringhe tra virgolette, poi esegue un :substitute solo entro le partite:?

/".\{-}" 
:SubstituteInSearch/_/ /g 
Problemi correlati