Thật là một cách hay để trích xuất, dòng 20 -45 trong một tệp văn bản lớn. Tất nhiên là không tương tác!
Thật là một cách hay để trích xuất, dòng 20 -45 trong một tệp văn bản lớn. Tất nhiên là không tương tác!
Câu trả lời:
bạn có thể thử:
cat textfile | head -n 45 | tail -n 26
hoặc là
cat textfile | awk "20 <= NR && NR <= 45"
cập nhật:
Như Mahomedalid đã chỉ ra, cat
không cần thiết và hơi dư thừa, nhưng nó làm cho một lệnh sạch, dễ đọc.
Nếu cat
làm phiền bạn, một cách giải quyết tốt hơn sẽ là:
<textfile awk "20 <= NR && NR <= 45"
,
toán tử phạm vi của awk .
Thậm chí đơn giản hơn:
sed -n '20,45p;45q' < textfile
Cờ -n vô hiệu hóa đầu ra mặc định. Bao gồm các địa chỉ "20,45" từ 20 đến 45. Lệnh "p" in dòng hiện tại. Và q thoát ra sau khi in dòng.
q
lệnh (mọi thứ bắt đầu từ ;
) đã cải thiện hiệu suất cho tôi khi trích xuất một dòng 26995107 từ tệp 27169334.
Đây không phải là một câu trả lời nhưng không thể đăng nó như một bình luận.
Một cách khác (rất nhanh) để làm điều đó đã được mikeerv đề xuất ở đây :
{ head -n 19 >/dev/null; head -n 26; } <infile
Sử dụng cùng một tệp kiểm tra như ở đây và cùng một quy trình, đây là một số điểm chuẩn (trích xuất các dòng 1000020-1000045):
mikeerv :
{ head -n 1000019 >/dev/null; head -n 26; } <iplist
real 0m0.059s
Stefan :
head iplist -n 1000045 | tail -n 26
real 0m0.054s
Đây là những giải pháp nhanh nhất và sự khác biệt là không đáng kể (cho một lần vượt qua) (tôi đã thử với các phạm vi khác nhau: một vài dòng, hàng triệu dòng, v.v.).
Tuy nhiên, làm điều đó mà không có đường ống có thể mang lại một lợi thế đáng kể cho một ứng dụng cần tìm kiếm trên nhiều phạm vi dòng theo cách tương tự, như:
for pass in 0 1 2 3 4 5 6 7 8 9
do printf "pass#$pass:\t"
head -n99 >&3; head -n1
done <<1000LINES 3>/dev/null
$(seq 1000)
1000LINES
... mà in ...
pass#0: 100
pass#1: 200
pass#2: 300
pass#3: 400
pass#4: 500
pass#5: 600
pass#6: 700
pass#7: 800
pass#8: 900
pass#9: 1000
... và chỉ đọc tệp qua một lần.
Các sed
/ awk
/ perl
giải pháp khác đọc toàn bộ tệp và vì đây là về các tệp lớn, nên chúng không hiệu quả lắm. Tôi đã ném vào một số lựa chọn thay thế exit
hoặc q
uit sau dòng cuối cùng trong phạm vi được chỉ định:
Stefan :
awk "1000020 <= NR && NR <= 1000045" iplist
real 0m2.448s
so với
awk "NR >= 1000020;NR==1000045{exit}" iplist
real 0m0.243s
dkagedal ( sed
):
sed -n 1000020,1000045p iplist
real 0m0.947s
so với
sed '1,1000019d;1000045q' iplist
real 0m0.143s
Steven D :
perl -ne 'print if 1000020..1000045' iplist
real 0m2.041s
so với
perl -ne 'print if $. >= 1000020; exit if $. >= 1000045;' iplist
real 0m0.369s
awk NR==1000020,NR==1000045 textfile
trong hệ thống của bạn.
ruby -ne 'print if 20 .. 45' file
python -c 'import fileinput, sys; [sys.stdout.write(line) for nr, line in enumerate(fileinput.input()) if 19 <= nr <= 44]'
quá? :-P Đây là điều mà Ruby, được mô phỏng theo Perl, lấy cảm hứng từ awk / sed, có thể thực hiện dễ dàng.
Vì sed và awk đã được sử dụng, đây là một giải pháp perl:
perl -nle "print if ($. > 19 && $. < 46)" < textfile
Hoặc, như được chỉ ra trong các ý kiến:
perl -ne 'print if 20..45' textfile
perl -ne'print if 20..45' textfile
awk NR==20,NR==45 textfile
hoạt động quá, và đọc dễ dàng.