2011-12-17 11 views
12

Potrzebuję przenieść zawartość co drugiego wiersza do powyższej linii, tak aby dane linii2 były wzdłuż linii 1, czyli przecinków lub oddzielonych spacjami.Jak połączyć pary kolejnych linii w dużym pliku (1 milion linii) za pomocą vim, sed lub innego podobnego narzędzia?

Wejście:

line1 
line2 
line3 
line4 

wyjściowa:

line1 line2 
line3 line4 

Robiłem to w vim za pomocą prostego zapisu ale vim wydaje się upaść, gdy mówię jej to zrobić 100 000 razy. .. Myślę, że może sed byłby dobrą alternatywą, ale nie wiem, jak to zrobić, co chcę, czy może jest lepsza opcja?

Każda linia zawiera tylko 1 wartość liczbową, mam tylko milion linii ...

+1

proszę sformatować pytanie i pokazać nam prawidłowe wejście i oczekiwany wynik. –

Odpowiedz

14

Jeśli dobrze rozumiem, masz:

i chcesz:

line1<SEP>line2 
line3<SEP>line4 

to można łatwo zrobić z (g)awk w ten sposób:

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

See it in action here.

Aktualizacja: jeśli liczba linii jest nieparzysta, powyższe będzie pominąć ostatnią linię (jak Martin Stettner wskazał), więc to nie będzie:

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

HTH

+1

Czy ten skrypt nie pomijałby ostatniego wiersza, jeśli masz nieparzystą liczbę linii? – MartinStettner

+0

@MartinStettner masz rację. Aktualizowanie rozwiązania. –

7

spróbuj tego:

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

testu z SEQ:

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 działa zbyt:

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

Test

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

To może pracować dla Ciebie:

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

Albo

cat file | paste -d' ' - - 
6

Twój przykład jest taki w Vimie.

:g/^/+t.|-j

Ale co z ostatniej linii?

Czy to miałeś na myśli?

:g/^/j 

Możesz być również zainteresowany tym skrypcie Vima, co sprawia czynienia z dużymi plikami łatwiejsze.

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

+0

Cześć, wow, wiedziałem, że musi być lepszy sposób, niż próbowałem !! :) Dzięki za mnóstwa opcji: g/^/j był najprostszy i robi to świetnie! – janeruthh

+0

Edytował OP zgodnie z powyższymi wyjaśnieniami powyżej. Pierwsza sugestia w mojej odpowiedzi może teraz zostać zignorowana. – 1983

+0

Wielka wskazówka Vima! W moim przypadku nie był to cały plik, więc można użyć opcji wyboru wizualnego ': '<,'> g/^/j' lub między _a mark_ a bieżącą linią':' a, .g/^/j' w celu ograniczenia dołączenie do mojego zakresu zainteresowania. Robi to 773 razy ręcznie! – 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 

uwaga:$ seq 10 >num.txt

+0

Co powiesz na "perl"? 'seq 10 | perl -pe '$ a ++% 2 || s/\ n//' ' – Sorpigal

5

Komenda pasta może to zrobić. Jego "-s" opcja będzie łączyć kolejne linie; a opcja "-d" określa listę znaków do użycia jako separatory, powtarzając je cyklicznie. Dołącz najpierw z miejsca, a następnie z nową linią, i powtarzać:

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

To rozwiązanie wykorzystuje "potrójny operator", aby ustawić 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)