2011-12-17 9 views
12

Ho bisogno di spostare il contenuto di ogni seconda riga fino alla linea sopra, in modo che i dati di line2 siano accanto a quelli di line1, sia separati da virgola che separati da spazi.Come unire coppie di righe consecutive in un file di grandi dimensioni (1 milione di righe) utilizzando vim, sed o un altro strumento simile?

ingresso:

line1 
line2 
line3 
line4 

uscita:

line1 line2 
line3 line4 

ho fatto in vim con una semplice registrazione, ma vim sembra bloccarsi quando dico di farlo 100 000 volte. .. Sto pensando che forse sed sarebbe una buona alternativa, ma non sono sicuro di come fare ciò che voglio o forse c'è un'opzione migliore?

Ogni riga contiene solo 1 valore numerico, non mi resta che un milione di linee ...

+1

Si prega di formattare la tua domanda, e ci mostrano il corretto ingresso e risultato atteso. –

risposta

14

Se ho capito bene, si hanno:

e si desidera:

line1<SEP>line2 
line3<SEP>line4 

quindi puoi farlo facilmente con (g)awk in questo modo:

awk 'NR % 2 == 1 { o=$0 ; next } { print o "<sep>" $0 }' INPUTFILE 

See it in action here.

Aggiornamento: se il numero di righe è dispari, quanto sopra si omette l'ultima riga (come Martin Stettner ha sottolineato), quindi questo non sarà:

awk 'NR % 2 == 1 { o=$0 ; next } { print o "<sep>" $0 } END { if (NR % 2 == 1) { print o } }' INPUTFILE 

HTH

+1

Questo script non dovrebbe omettere l'ultima riga nel caso in cui si disponga di un numero dispari di righe? – MartinStettner

+0

@MartinStettner hai ragione. Aggiornamento della soluzione. –

7

provare questo:

sed -rn 'N;s/\n/ /;p' yourFile 

test con seguenti:

kent$ seq 10 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 

kent$ seq 10|sed -rn 'N;s/\n/ /;p' 
1 2 
3 4 
5 6 
7 8 
9 10 

awk lavora troppo:

awk 'NR%2{printf $0" ";next;}1' yourFile 

prova

kent$ seq 10|awk 'NR%2{printf $0" ";next;}1' 
1 2 
3 4 
5 6 
7 8 
9 10 
6

Questo potrebbe funzionare per voi:

sed 'N;s/\n/ /' file 

O

cat file | paste -d' ' - - 
6

Bene, il tuo esempio è questo in Vim.

:g/^/+t.|-j

Ma allora che cosa circa l'ultima riga?

O intendevi questo?

:g/^/j 

si potrebbe anche essere interessato a questo script di Vim, che fa fare con file di grandi dimensioni più facile.

http://www.vim.org/scripts/script.php?script_id=1506

+0

Ciao, wow, sapevo che ci doveva essere un modo migliore di quello che stavo cercando !! :) Grazie per il sacco di opzioni,: g/^/j è stato il più semplice e fa il lavoro alla grande! – janeruthh

+0

Modificato l'OP in seguito alla precisazione sopra riportata. Il primo suggerimento nella mia risposta può ora essere ignorato. – 1983

+0

Ottimo consiglio Vim! Nel mio caso, non era l'intero file, quindi può usare una selezione visiva ': '<,'> g/^/j' o tra il segno _a e la riga corrente':' a, .g/^/j' per limitare l'adesione al mio raggio d'interesse. Batte facendolo 773 volte manualmente! – ddevienne

2
$ seq 10 | sed '2~2G' | awk -v RS='' '{$1=$1; print}' 
1 2 
3 4 
5 6 
7 8 
9 10 

$ paste -d' ' <(sed -n 'p;n' num.txt) <(sed -n 'n;p' num.txt) 
1 2 
3 4 
5 6 
7 8 
9 10 

$ echo -e 'g/^/,+1j\n%p' | ex num.txt 
1 2 
3 4 
5 6 
7 8 
9 10 

$ seq 10 | awk 'NR%2{printf("%s ", $0); next}1' 
1 2 
3 4 
5 6 
7 8 
9 10 

$ seq 10 | sed 'N;s/\n/ /' 
1 2 
3 4 
5 6 
7 8 
9 10 

nota:$ seq 10 >num.txt

+0

Che ne dici di 'perl'? 'seq 10 | perl -pe '$ a ++% 2 || s/\ n//' ' – Sorpigal

5

il comando Incolla può fare questo. La sua opzione "-s" si unirà a linee consecutive; e l'opzione "-d" specifica un elenco di caratteri da usare come delimitatori, ripetendoli ciclicamente. Registrazione prima con uno spazio, poi con un ritorno a capo, e ripetere:

seq 10 | paste -sd" \n" - 
0
seq 10 | awk 'ORS=NR%2?FS:RS' 

Questa soluzione utilizza "operatore ternario" per impostare ORS

ORS= ....... output register separator (will receive =) 
NR%2 ....... test if it has division remainder of Number of Register by 2 
?FS:RS ..... FS = "space" RS = "\n" (newline) 
Problemi correlati