2010-06-04 11 views
7

I Text im follwing Format haben:vim regex für den Ersatz Räume in Anführungszeichen

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

Ich möchte alle Leerzeichen in den Text ersetzen, die mit Unterstrichen in Anführungszeichen sind:

ERR_OUT_OF_MEM, "ERR_OUT_OF_MEM" 
ERR_SOMETHING_BAD, "ERR_SOMETHING_BAD" 

Die beste regex ich tun konnte, ist:

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

(ein Raum ist am Ende, dass)

aber dies findet nur den ersten Platz in jedem String zitiert, und ich brauchen würde dies mehrere Male zu wiederholen, um den gewünschten Effekt zu erzielen.

Jede Art und Weise es in einem Schuss zu tun?

Danke!

Antwort

6

Es ist sicherlich ein 0-Länge Muster, das in einem Durchgang funktioniert, aber da ich nie viel Erfolg mit ihnen haben, ziehe ich diese Art von Ansatz:

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

Hinweis: doppelte Anführungszeichen gruppiert gehalten werden 2 von 2 um

foo bar "foo bar" "foo barr" 

in

foo bar "foo_bar"_"foo_barr" 

EDIT nicht zu verwandeln: als rampion wies o ut, ist die folgende mehr als genug:

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

Warum nicht nur das '/„[^“] *"/'Muster, das ich nicht bekommen, was die ersten Paare von Anführungszeichen Überspringen kauft man (mit '\% ("[^"] *" \) * ') – rampion

+0

Guter Punkt. Ich war überzeugt, dass die Suche starten würde nicht wieder nach dem Schlusskurs, aber nach der Eröffnung ein. Ich korrigiere die Regex. Vielen Dank. –

6

Dies ist keine Allzwecklösung, da es keinen Platz übereinstimmen, die überall nach einem doppelten Anführungszeichen in einer Zeile erscheint, aber es sollte in für Strings arbeiten das Format, das Sie angegeben haben:

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

ich habe das \ v verwendet (verymagic) Token, weil ich denke, es ist die Regex ein wenig besser lesbar macht, und ich gehörte die ganze Substitution Befehl, da die ‚g‘ Am Ende ist es wichtig.

Für jene entlang zu Hause folgen, diese Regex ‚verymagic‘ -Modus ersten Sätze mit \ v. Dann definiert es das Token (\".*), was grob "ein Doppelzitat und dann noch irgendwas anderes" bedeutet und verwendet die Lookbehind-Behauptung @<= um zu sagen "nur Dinge nach dem letzten Token" zu vergleichen - mit anderen Worten, nur Dinge, die nach einem doppelten Zitat kommen . Schließlich gibt es ein Leerzeichen, das tatsächlich abgeglichen wird, und der Substitutionsbegriff ist ein Unterstrich, mit dem wir ihn ersetzen wollen, und die g sagt "Ersetze alle passenden Terme", so dass wir nicht nur den ersten erhalten Übereinstimmung gefunden.

+0

Das funktioniert, aber es ersetzt auch Leerzeichen, die ich am Ende der Zeile habe. –

+0

Ah. Ja, wenn Sie nachgestellte Leerzeichen haben, benötigen Sie einen komplexeren Ansatz. Luc, oben, sollte es tun. –

0

Mein PatternsOnText plugin bietet einen :SubstituteInSearch Befehl. Damit Sie erste Suche nach den Saiten zitiert, dann führen Sie ein :substitute nur innerhalb der Matches:

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