2011-07-25 3 views
14

Tôi đã tự hỏi nếu có một cách hiệu quả hơn để hoàn thành công việc này. Tôi đang làm việc với các tệp có số dòng từ vài trăm nghìn đến vài triệu. Giả sử tôi biết rằng các dòng 100.000 - 125.000 là các dòng chứa dữ liệu tôi đang tìm kiếm. Tôi muốn biết nếu có một cách nhanh chóng để kéo chỉ những dòng mong muốn từ tập tin. Hiện tại, tôi đang sử dụng vòng lặp với grep như sau:bash kéo một số dòng nhất định từ một tệp

for ((i=$start_fid; i<=$end_fid; i++)) 
    do 
    grep "^$i " fulldbdir_new >> new_dbdir${bscnt} 
    done 

Làm việc tốt chỉ mất nhiều thời gian hơn tôi muốn. Và các dòng chứa nhiều hơn chỉ là số. Về cơ bản, mỗi dòng có khoảng 10 trường với số thứ nhất là số nguyên tuần tự chỉ xuất hiện một lần cho mỗi tệp.

Tôi cảm thấy thoải mái khi viết bằng C nếu cần.

Trả lời

20

sed có thể thực hiện công việc ...

sed -n '100000,125000p' input

EDIT: Theo đề nghị của glenn jackman, có thể được điều chỉnh thusly cho hiệu quả ...

sed -n '100000,125000p; 125001q' input

+4

thêm một số hiệu quả với 'sed -n' 100000,125000p; 125001q'' –

+0

Tuyệt vời! Cảm ơn cho rằng – Costa

+0

Tôi nghĩ rằng câu trả lời này sẽ làm việc cho tôi, những gì hiện các p và q đứng sau 125000 và 125001 tương ứng? – mike

2

Bạn có thể thử kết hợp đuôi và đầu để có các đường chính xác.

head -n 125000 file_name | tail -n 25001 | grep "^$i " 

Đừng quên perl.

perl -ne 'print if $. >= 100000 && $. <= 125000' file_name | grep "^$i " 

hoặc một số perl nhanh hơn:

perl -ne 'print if $. >= 100000; exit() if $. >= 100000 && $. <= 125000' | grep "^$i " 

Ngoài ra, thay vì một vòng lặp for, bạn có thể muốn xem xét sử dụng GNU parallel.

5

Tôi muốn sử dụng awk:

awk 'NR >= 100000; NR == 125000 {exit}' file 

Đối với số lượng lớn bạn cũng có thể sử dụng E ký hiệu:

awk 'NR >= 1e5; NR == 1.25e5 {exit}' file 

EDIT: @glenn jackman của đề nghị (x bình luận)

+3

Tiết kiệm thời gian với 'NR> 125000 {thoát}' –

+0

@glenn jackman: v. Điểm tốt. tôi sẽ cập nhật. – mhyfritz

0

Những câu trả lời cho đến nay đọc 100000 dòng đầu tiên và loại bỏ chúng. Vì đĩa I/O thường là yếu tố hạn chế nên có thể có một giải pháp không cần phải đọc các dòng không mong muốn. Nếu 100000 dòng đầu tiên luôn có tổng chiều dài tương đương (xấp xỉ), thì bạn có thể tính toán khoảng cách để tìm kiếm tệp đến gần 100000 dòng và sau đó đọc 25000 dòng tiếp theo. Có thể đọc thêm một chút trước và sau để đảm bảo bạn có tất cả 25000 dòng.

Bạn sẽ không biết chính xác bạn đang ở đâu, mặc dù điều đó có thể hoặc có thể không quan trọng đối với bạn.

Giả sử độ dài đường trung bình của 100000 dòng đầu tiên là 130 sau đó bạn sẽ nhận được một cái gì đó như thế này:

dd if=the_file skip=130 bs=100000 | head -n 25000 

Bạn sẽ phải vứt bỏ dòng đầu tiên, vì nó có khả năng là chỉ nửa hàng.