2010-01-03 6 views
5

Ho un file di testo (più correttamente, uno “ stile tedesco “ file CSV, cioè virgola decimale separata da punto e virgola) che ha una data e il valore di una misura su ciascuna linea.
Ci sono tratti di valori errati che voglio rimuovere prima di ulteriori interventi. Mi piacerebbe archiviare questi tagli in alcuni script in modo che le mie correzioni siano documentate e se possibile rieseguo tali correzioni.Rimuovere le righe tra determinati modelli da un file (utilizzando gli strumenti Unix)

Le linee simile a questa:

28.01.2005 14:48:38;5,166 
28.01.2005 14:50:38;2,916 
28.01.2005 14:52:38;0,000 
28.01.2005 14:54:38;0,000 
(long stretch of values that should be removed; could also be something else beside 0) 
01.02.2005 00:11:43;0,000 
01.02.2005 00:13:43;1,333 
01.02.2005 00:15:43;3,250 

Ora mi piacerebbe memorizzare un elenco di iniziare e di fine modelli come 28.01.2005 14:52:38 + 01.02.2005 00:11:43, e lo script avrebbe tagliato le linee corrispondenti a questi iniziano coppie/fine e tutto ciò che c'è tra di loro.

Sto pensando di hackerare uno script awk, ma forse mi manca uno strumento già esistente.

(linee di stampa nessuna corrispondenza)

risposta

16

Dai un'occhiata alla sed:

sed '/start_pat/,/end_pat/d' 

cancellerà linee tra start_pat e end_pat (incluso).

Per eliminare più tali coppie, è possibile combinarli con più -e opzioni:

sed -e '/s1/,/e1/d' -e '/s2/,/e2/d' -e '/s3/,/e3/d' ... 
+0

Ottimo! Sapevo che mi mancava qualcosa e hellip; Ho sempre usato sed con modelli singoli e non ho mai ricordato che offre gamme. –

+0

Inoltre, posso inserire le espressioni in un file, dove posso anche usare commenti (con '#'). La riga di comando è quindi "file-script script sed -f ". –

-1

uso grep -L

Spiacente - pensavano si voleva solo righe senza 0,000 alla fine

+0

grep -L stamperà nomi di file non corrispondenti. grep -v stamperebbe linee non corrispondenti, ma l'OP sembra essere dopo qualcosa di più complicato (usando intervalli). – mopoke

+0

Ok pensavo volessero stampare qualsiasi cosa senza 0.000 alla fine –

+0

In effetti, il mio esempio era un po 'ingannevole – ci sono altri valori errati oltre a 0, ad es. quelli negativi. –

0

In primo luogo, perché avete bisogno di tenere un registro di quello che hai fatto? Perché non conservare un backup del file originale o prendere un diff tra i vecchi & nuovi file o metterlo sotto il controllo del codice sorgente?

Per le modifiche effettive suggerisco di utilizzare Vim.

Il comando Vim :global (abbreviato in :g) può essere utilizzato per eseguire: comandi ex su righe che corrispondono a un'espressione regolare. Questo è in molti modi più potente di awk poiché i comandi possono quindi fare riferimento a intervalli relativi alla linea corrispondente, in più hai a disposizione la potenza completa di elaborazione del testo di Vim.

Ad esempio, questo farà qualcosa di simile a ciò che si vuole (non testato, caveat in modo caveat):

:g!/^\d\d\.\d\d\.\d\d\d\d/ -1 write tmp.txt >> | delete 

Ciò corrisponde a righe che non iniziano con una data (il ! nega la partita), accodamento la riga precedente al file tmp.txt, quindi elimina la riga corrente.

Probabilmente finirai con le righe duplicate in tmp.txt, ma possono essere rimosse eseguendo il file tramite uniq.

+0

Vorrei tenere brevi note sui dischi che ho buttato fuori e perché. Lavorerò con questi dati non molto frequentemente, e so che potrei dimenticare ciò che avevo fatto. Inoltre, qualcun altro potrebbe aver bisogno di capire e riprodurre ciò che ho fatto. Purtroppo, l'esempio di vi/ex in realtà non risolve il mio problema, perché tutte le linee iniziano con una data. Ma capisco la direzione che stai indicando. –

0

siete anche utilizzare awk

awk '/start/,/end/' file 
+1

Da qualche parte è stato detto che awk è appropriato dove i dati sono rappresentati in formato colonna. È corretto. Potresti spiegare se awk è meglio che sed per ** questo ** compito particolare. –

0

Vorrei seriamente suggerire imparare le basi di Perl (vale a dire non la roba OO). Ti ripagherà in carichi secchi.

È facile e veloce scrivere un po 'di perl per fare questo (e molti altri simili compiti) una volta afferrati i fondamenti, che se siete abituati a usare awk, sed, grep ecc sono piuttosto semplici.

Non dovrai ricordare come utilizzare molti strumenti diversi e in cui in precedenza avresti utilizzato più strumenti collegati per risolvere un problema, puoi semplicemente utilizzare un singolo script perl (in genere molto più veloce da eseguire).

E, perl è installato su praticamente ogni distro unix/linux ora.

(che sed è pulito però :-)