`Wc -l` hoạt động như thế nào?


11

Tôi phải đọc một tệp lớn và trước khi bắt đầu đọc nó, tôi cần biết tổng số dòng trong tệp (tính bằng triệu).

Tôi đã thực hiện rất nhiều giải pháp và đã tìm thấy một. Nhưng trong quá trình tìm kiếm, tôi đã suy nghĩ để xem cách thức wc -lhoạt động. Tôi không thể tìm thấy bất cứ điều gì trên Google.

Mặc dù tôi đã tìm ra giải pháp cho vấn đề của mình, tôi vẫn muốn biết cách wc -lhoạt động vì nó có thể tính toán số dòng của một tệp với 92 Triệu dòng trong vài giây!

Làm sao?


Câu trả lời:


20

Nó đọc toàn bộ tập tin và đếm số lượng kết thúc dòng. Đếm kết thúc dòng thực sự rẻ; hầu hết thời gian dành cho việc đọc các tập tin. Nếu tập tin xảy ra (chủ yếu) trong bộ đệm bộ đệm, điều đó cũng sẽ rẻ. Nếu không, nó sẽ phụ thuộc vào tốc độ lưu trữ tệp của bạn.

Nói cách khác, không có phép thuật.


Nó đọc toàn bộ tập tin và đếm số lượng kết thúc dòng? Để đi đến kết thúc dòng, về cơ bản nó không đọc toàn bộ dòng cho đến khi kết thúc? Và điều đó có nghĩa là nó đọc toàn bộ tập tin, phải không?
gièm pha

@detraveller: vâng, nó đọc toàn bộ tập tin, như tôi đã nói. Nó không đọc từng dòng một hoặc tất cả cùng một lúc, nhưng nó đọc mọi ký tự và đếm xem có bao nhiêu trong số các ký tự đó là các ký tự cuối dòng.
rici

7

WC chỉ đọc tệp theo các khối byte thô (tốt nhất là theo bội số của kích thước khối tự nhiên của hệ thống tệp nằm bên dưới mà tệp được đặt).
Sau đó, nó chỉ quét qua bộ đệm đếm các ký tự cuối dòng. (Nó cũng tính khoảng trắng, tab, nguồn cấp dữ liệu và các ký tự đặc biệt khác, chỉ trong trường hợp bạn muốn có thông tin khác ngoài đầu ra -l.)

Đọc từ đĩa là phần tốn kém về tốc độ. Quá trình quét bộ đệm mất thời gian có thể bỏ qua so với điều đó.

Giả sử bạn đã có 90 triệu dòng với trung bình 100 ký tự trên mỗi dòng.
Đó là khoảng 9.000.000.000 ký tự hoặc khoảng 860 MB.
Một PC tốt với ổ đĩa SATA-3Gb / s sẽ làm điều đó dưới 10 giây. Ngay cả trên một hệ thống tập tin tương đối chậm với một số hoạt động khác đang diễn ra cùng một lúc.
Một cỗ máy nhanh với một số điều chỉnh hiệu suất và hệ thống tập tin được tối ưu hóa có thể làm điều đó trong vòng 5 giây, thậm chí không cần phải dùng đến SATA-6G và ổ SSD.


nó chỉ quét qua bộ đệm đếm các ký tự cuối dòng ( \n) - "-l, --lines in số dòng mới \ n \" - được trích xuất từwc.c
Rahul Patil

@RahulPatil Hầu hết các triển khai thực hiện nhiều hơn là chỉ đếm các dòng mới. Xem ví dụ được đề cập trong bình luận hàng đầu ở trên. Đó là nguồn wc như được sử dụng trong các tiện ích cốt lõi của Linux.
Tonny

vâng .. tôi đã thấy điều đó .. chỉ cần tôi đề cập bởi vì, câu hỏi về wc -l.. xin lỗi ...
Rahul Patil

3

Chào mừng đến với thế giới của phần mềm miễn phí. Bạn luôn có thể nhìn vào mã nguồn

Mặc dù tôi phải thừa nhận rằng tôi không phải là lập trình viên C, vì vậy tôi không phải là người thực sự có thể giải thích mã cho bạn (và tôi sẽ tự khắc phục mình).

Những gì tôi biết là vì wc không tự mở tệp, nhưng yêu cầu HĐH thực hiện, điều này phần lớn phụ thuộc vào HĐH, và tất nhiên, cách tệp được lưu trữ. Ngoài ra, tôi hy vọng rằng các thực tiễn lập trình chính xác phải được áp dụng, ví dụ như không cố gắng đọc toàn bộ tệp cùng một lúc, v.v.


Ý bạn là gì khi nói 'không cố đọc toàn bộ tập tin cùng một lúc'?
gièm pha

Tôi có nghĩa là tải tập tin vào bộ nhớ, giả sử, vào một chuỗi / mảng duy nhất. Trong cộng đồng Perl này được gọi là slurping, và đó là một giải pháp nhanh chóng & bẩn đó là OK khi bạn biết bạn sẽ được đọc vài dòng, nhưng ăn tập tin thực sự rất lớn vào bộ nhớ cùng một lúc là hiếm khi một ý tưởng tốt.
Alois Mahdal

1
Mặt khác, bạn có thể đọc, nói, 64 KiB, đếm số dòng mới và vứt nó đi, lặp lại ... Bằng cách đó, bạn sẽ ăn hết thứ gì đó trên 64 KiB, bất kể tập tin có lớn đến mức nào. (Sẽ dễ dàng hơn khi bạn nhận ra rằng dòng mới có thể có 2 byte và do đó được chia thành 2 phần; bây giờ đó là lúc niềm vui bắt đầu)
Alois Mahdal

Không quá quan trọng, nhưng: "vì wc không tự mở tệp, nhưng yêu cầu HĐH làm điều đó" - không chắc ý của bạn là gì, nhưng tôi nghi ngờ điều này là chính xác. Nó chắc chắn đọc tất cả các nhân vật của chính nó.
Arjan

2
@Arjan Mặc dù, để thực sự chính xác: ngoại trừ các hệ thống nhúng, các chương trình hầu như không thực sự tự đọc, toàn bộ quan điểm của Kernel và OS là nó thực hiện công việc cho chúng. Trong thực tế, open (), close (), read () (có thể là Linux, Windows, socket hoặc file) là tất cả các cuộc gọi hệ thống mà các chương trình thực tế không có ý tưởng về hoạt động bên trong.
Alois Mahdal
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.