Vim golf: correggi un CSV rotto


2

Ho un grande file CSV che dovrebbe avere due campi. Dovrebbe assomigliare sostanzialmente a questo:

1234, Some series of words
539345, Something else
2039, "quotes are, of course, necessary here"

Il problema è che mancano le virgolette sulla riga 3 e ci sono molte righe come questa. Ho registrato una macro per effettuare le seguenti operazioni:

  • Vai all'inizio di una riga
  • Passa al punto subito dopo la prima virgola
  • Inserisci una virgoletta
  • Vai alla fine della linea
  • Aggiungi un segno di virgolette

Tuttavia, anche con questa macro, devo scansionare manualmente il file, riproducendolo su righe con più virgole. Non posso farlo su ogni linea, perché non è un CSV valido.

Quello che mi piacerebbe è un comando di sostituzione che dice: "per le righe con più di una virgola, inserisci una virgoletta dopo la prima virgola e una virgoletta alla fine della riga".

Qualcuno si preoccupa di fare un salto a questo?


In realtà, penso che sia OK farlo su ogni riga, nel qual caso posso semplicemente eseguire la mia macro sull'intero file. Ma sono ancora interessato a vedere una risposta.
Nathan Long,

che cos'è 'vimgolf'?
Akira,

1
vimgolf sta risolvendo un problema con il minor numero di sequenze di tasti all'interno di vim.
Onnipotente,

Risposte:


3

Ecco un comando più breve senza gruppi di acquisizione. Usa &per ripetere la partita precedente. Ci sono due comandi separati da |. Il primo aggiunge la citazione dopo il primo "," e gli eventuali spazi che la seguono. Il secondo aggiunge una citazione alla fine della riga.

:g/,.*,/s/, */&"/|s/$/"/

'Il primo aggiunge la citazione dopo il primo ","' .. se non c'è già "(che è ciò che l'OP vuole, ma dovrebbe essere chiarito). E anteporre ciecamente un" a $ crea 'necessario qui ""' dati OP 3. campione, vero?
Akira,

@akira: ho preso i campioni per essere il "dopo" desiderato piuttosto che il "prima". Il mio comando ha lo stesso effetto di quello di Garyjohn, ma è più breve. Se vuoi assicurarti che l'ultimo personaggio non sia già una doppia virgoletta, modifica il secondo comando ins/[^"]$/&"/
Dennis Williamson,

Grande! Due cose: non sapevo che potresti passare i risultati :ga una sostituzione - sai dove posso leggere di più su questo? 2) Il | il separatore qui funziona come fa in bash - pipe l'output del primo comando all'input del secondo?
Nathan Long,

@GorillaSandwich: |è un separatore di comandi come ;in Bash. Ti permette di eseguire più di un comando. Non convoglia l'output dell'uno nell'altro. Vedere :h :bar. Puoi fare :h globalper vedere più informazioni su g(che accetta un comando come argomento) e :h /per vedere di più sulla ricerca (che è il comando in questo caso).
Dennis Williamson,

1
@Dennis Williamson: Non che io sappia, ma puoi aggiungere un prefisso a un comando ex :silent!per ignorare gli errori. In :silent! <command 1> | <command 2>, <comando 2> verrà eseguito anche se <comando 1> genera un errore.
Garyjohn,

2

Sicuro.

:g/,.*,/s/\(, *\)\(.*\)/\1"\2"/

Le g/,.*,/ricerche per ogni linea che contiene almeno due virgole. Il comando sostitutivo cerca una virgola seguita da zero o più spazi e la inserisce nel buffer di corrispondenza n. 1, quindi inserisce tutto il resto della riga nel buffer di corrispondenza n. 2. Infine, il comando sostitutivo sostituisce quelle due corrispondenze con la prima corrispondenza, quindi la seconda corrispondenza racchiusa tra virgolette.


Grazie per l'aiuto! Ho accettato la risposta di Dennis Williamson perché è più breve, ma entrambi avete fornito buone soluzioni di lavoro. Ti farò la stessa domanda che gli ho posto: non sapevo che potresti passare i risultati di: g a una sostituzione - sai dove posso leggere di più su questo?
Nathan Long,

@GorillaSandwich: Dennis Williamson non passa il risultato di: g a una sostituzione; sta passando la corrispondenza del modello del comando s alla sostituzione. Cioè, e rappresenta la corrispondenza a ", *", non la corrispondenza a ",. *,". Detto questo, puoi passare il risultato di: g a una sostituzione lasciando vuoto il modello del comando s, ad es :g/.*/s//"&"/. Non ho un ottimo riferimento per questo, ma puoi saperne di più da :help s/\&e :help mulit-repeat(saltare al secondo paragrafo dalla parte inferiore della sezione).
Garyjohn,

@garyjohn: FYI, si potrebbe fare a meno sfuggire se si è utilizzato \v: :g/,.*,/s/\v(, *)(.*)/\1"\2"/.
idbrii,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.