2012-03-27 10 views
22

consideri un file di testo con i dati scientifici, ad es .:Come posso eliminare ogni X riga in un file di testo?

5.787037037037037063e-02 2.048402977658663748e-01 
1.157407407407407413e-01 4.021264347118673754e-01 
1.736111111111111049e-01 5.782032163406526371e-01 

Come posso eliminare facilmente, per esempio, ogni seconda linea, oppure ogni 9 su 10 linee nel file? Per esempio è possibile con uno script bash?

Sfondo: il file è molto grande ma ho bisogno di molto meno dati da tracciare. Nota che sto usando Ubuntu/Linux.

+0

Sei sicuro di voler puntare-campionare i dati come questo? Potrebbe essere meglio fare un downsampling, in cui i dati provenienti da gruppi di N linee sono mediati in qualche modo appropriato. Il campionamento puntuale porta potenzialmente a problemi di aliasing. – Kaz

+0

http: //unix.stackexchange.it/questions/168004/delete-every-nth-line-in-shell –

risposta

53

Questo è facile da realizzare con awk.

Rimuovere ogni altra linea:

awk 'NR % 2 == 0' file > newfile 

Rimuovere ogni linea 10:

awk 'NR % 10 != 0' file > newfile 

La variabile NR in awk è il numero di riga. Qualunque cosa al di fuori di {} in awk è un condizionale e l'azione predefinita è quella di stampare.

+0

Mai sentito parlare di awk prima. Lo controlleremo sicuramente ora! Grazie! – Ingo

+0

Awk è molto utile per l'elaborazione del testo negli script di shell. Può anche fare matematica in virgola mobile, che bash non può fare. Sicuramente vale la pena di imparare per i programmatori di shell. – jordanm

+1

Il primo comando lascia le linee con ID pari in posizione, non lo rimuove. Se vuoi rimuoverlo, usa awk 'NR% 2! = 0' file> newfile. – Olga

2

provare qualcosa di simile:

awk 'NR%3==0{print $0}' file 

Questo stamperà una riga su tre. Oppure:

awk 'NR%10<9{print $0}' file 

stampa 9 righe su dieci.

+1

Stampa è l'azione predefinita, quindi 'print $ 0' non è necessario. – jordanm

+0

Lo so. Sembra troppo strano per me però. (Non sono un utente awk esperto.) – Mat

+0

NR% 10 non potrebbe mai essere più di 9 ... – 123

2

È possibile farlo con sed, ad es.

sed -n -e 'p;N;d;' file # print every other line, starting with line 1 

Se avete GNU sed è abbastanza facile

sed -n -e '0~10p' file # print every 10th line 
sed -n -e '1~2p' file # print every other line starting with line 1 
sed -n -e '0~2p' file # print every other line starting with line 2 
0

È possibile utilizzare uno script awk e uno shell. Awk può essere difficile, ma ...

Questo cancellerà linee specifiche si dice di:

nawk -f awkfile.awk [filename] 

awkfile.awk contents 

BEGIN { 
if (!lines) lines="3 4 7 8" 
n=split(lines, lA, FS) 
for(i=1;i<=n;i++) 
linesA[lA[i]] 
} 
!(FNR in linesA) 

Anche io non riesco a ricordare se VIM viene fornito con lo standard di Ubuntu oppure no. Se non capisco.

quindi aprire il file con vim vim [nome del file]

quindi digitare

:%!awk NR\%2 or :%!awk NR\%2 

Questo cancellerà ogni altra linea. Basta cambiare il 2 in un altro intero per una frequenza diversa.

6

Che ne dici di perl?

perl -n -e '$.%10==0&&print'  # print every 10th line 
+0

Vuole eliminare ogni 10ª linea, invece di mantenere ogni 10 riga. Facile modifica del codice,! = Invece di ==. – jordanm

+2

No. Dichiara "Come posso cancellare facilmente **, ad esempio, ogni seconda riga, o ** ogni 9 su 10 ** linee nel file?", Eliminare ogni 9 righe su 10 significa stampare ogni 10 °. Come dici tu, una volta che la soluzione è stata pubblicata è facile adattarsi quindi non mi sono preso la briga di correggere altri poster che hanno commesso lo stesso errore. – Sorpigal

+0

Dopo aver riletto di nuovo la domanda, credo che la tua interpretazione sia quella giusta. – jordanm

2

Questo potrebbe funzionare per voi (GNU SED):

seq 10 | sed '0~2d' # delete every 2nd line 
1 
3 
5 
7 
9 
seq 100 | sed '0~10!d' # delete 9 out of 10 lines 
10 
20 
30 
40 
50 
60 
70 
80 
90 
100 
Problemi correlati