2011-12-17 16 views
12

Tôi cần phải di chuyển nội dung của mỗi dòng thứ hai lên đến dòng ở trên sao cho dữ liệu của dòng 2 nằm dọc theo dòng 1, hoặc là dấu phẩy hoặc khoảng trắng được phân tách.Làm cách nào để ghép các cặp liên tiếp vào một tệp lớn (1 triệu dòng) bằng cách sử dụng vim, sed hoặc một công cụ tương tự khác?

Input:

line1 
line2 
line3 
line4 

Output:

line1 line2 
line3 line4 

Tôi đã thực hiện nó trong vim với ghi âm đơn giản nhưng vim dường như sụp đổ khi tôi nói với nó để làm điều đó 100 000 lần. .. Tôi nghĩ rằng có lẽ sed sẽ là một lựa chọn tốt nhưng không chắc chắn làm thế nào để làm những gì tôi muốn hoặc có thể có một lựa chọn tốt hơn?

Mỗi dòng chỉ chứa 1 giá trị số, tôi chỉ có một triệu dòng ...

+1

hãy định dạng câu hỏi của bạn, và cho chúng ta thấy đầu vào thích hợp và dự kiến ​​đầu ra. –

Trả lời

14

Nếu tôi hiểu đúng, bạn có:

và bạn muốn:

line1<SEP>line2 
line3<SEP>line4 

thì bạn có thể thực hiện dễ dàng với (g)awk như sau:

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

See it in action here.

Cập nhật: nếu số dòng là số lẻ, bên trên sẽ bỏ qua các dòng cuối cùng (như Martin Stettner chỉ ra) vì vậy đây sẽ không:

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

HTH

+1

Tập lệnh này có bỏ qua dòng cuối cùng trong trường hợp bạn có một số dòng lẻ không? – MartinStettner

+0

@MartinStettner bạn nói đúng. Cập nhật giải pháp. –

7

thử điều này:

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

thử nghiệm với 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 làm việc quá:

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

kiểm tra

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

Điều này có thể làm việc cho bạn:

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

Hoặc

cat file | paste -d' ' - - 
6

Ví dụ của bạn là ở Vim.

:g/^/+t.|-j

Nhưng sau đó những gì về dòng cuối cùng?

Hay bạn có ý đó?

:g/^/j 

Tập lệnh Vim này, giúp bạn xử lý các tệp lớn dễ dàng hơn.

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

+0

Xin chào, wow, tôi biết phải có một cách tốt hơn tôi đã cố gắng !! :) Cảm ơn bạn đã tải các tùy chọn,: g/^/j là đơn giản nhất và thực hiện công việc tuyệt vời! – janeruthh

+0

Đã chỉnh sửa OP theo cách giải thích ở trên ở trên. Đề xuất đầu tiên trong câu trả lời của tôi giờ đây có thể bị bỏ qua. – 1983

+0

Mẹo Vim tuyệt vời! Trong trường hợp của tôi, không phải toàn bộ tập tin, vì vậy có thể sử dụng Visual Selection ': '<,'> g/^/j' hoặc giữa _a mark_ và dòng hiện tại':' a, .g/^/j' để giới hạn sự tham gia vào phạm vi quan tâm của tôi. Beats làm nó 773 lần thủ công! – 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 

lưu ý:$ seq 10 >num.txt

+0

Làm thế nào về 'perl'? 'seq 10 | perl -pe '$ a ++% 2 || s/\ n//' ' – Sorpigal

5

Lệnh dán có thể làm điều này. Tùy chọn "-s" của nó sẽ tham gia các dòng liên tiếp; và tùy chọn "-d" chỉ định danh sách các ký tự để sử dụng làm dấu phân cách, lặp lại chúng theo chu kỳ. Tham gia đầu tiên với một không gian, sau đó với một dòng mới, và lặp lại:

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

Giải pháp này sử dụng "nhà điều hành ternary" để thiết lập 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)