Jak działa `wc -l`?


11

Muszę przeczytać duży plik i zanim zacznę go czytać, muszę znać całkowitą liczbę wierszy w pliku (w milionach).

Wdrożyłem wiele rozwiązań i znalazłem jedno. Ale podczas moich poszukiwań zastanawiałem się, jak to wc -ldziała. Nie mogłem nic znaleźć w Google.

Chociaż znalazłem rozwiązanie mojego problemu, nadal chciałbym wiedzieć, jak to wc -ldziała, ponieważ może obliczyć liczbę linii pliku z 92 milionami linii w ciągu kilku sekund!

W jaki sposób?


Odpowiedzi:


20

Czyta cały plik i liczy liczbę zakończeń linii. Liczenie zakończeń linii jest naprawdę tanie; większość czasu spędza na czytaniu pliku. Jeśli plik znajdzie się (głównie) w pamięci podręcznej bufora, to też będzie tanie. W przeciwnym razie będzie to zależeć od szybkości przechowywania plików.

Innymi słowy, nie ma magii.


Czyta cały plik i liczy liczbę zakończeń linii? Aby dostać się do końca linii, czy w zasadzie nie odczytuje całej linii aż do końca? A to oznaczałoby odczytanie całego pliku, prawda?
detraveller

@ detraveller: tak, czyta cały plik, tak jak powiedziałem. Nie odczytuje go wiersz po wierszu lub wszystkich naraz, ale odczytuje każdy znak i liczy, ile z tych znaków to znaki końca linii.
rici

7

WC po prostu odczytuje plik w blokach surowych bajtów (najlepiej w wielokrotnościach naturalnego rozmiaru bloku bazowego systemu plików, na którym znajduje się plik).
Następnie skanuje tylko bufor, licząc znaki końca linii. (Zlicza również spacje, tabulatory, formularze i inne znaki specjalne, na wypadek, gdybyś potrzebował innych informacji niż wyjście -l.)

Odczytywanie z dysku jest kosztowną częścią pod względem prędkości. Skanowanie bufora zajmuje w porównaniu z tym czas do pominięcia.

Załóżmy, że masz 90 milionów linii ze średnio 100 znakami w linii.
To około 9 000 000 000 znaków lub około 860 MB.
Dobry komputer z napędem SATA-3Gb / s zrobi to w mniej niż 10 sekund. Nawet na stosunkowo wolnym systemie plików z pewną inną aktywnością.
Szybka maszyna z dostrajaniem wydajności i zoptymalizowanym systemem plików może to zrobić w ciągu 5 sekund, nawet bez konieczności uciekania się do SATA-6G i napędu SSD.


to właśnie skanuje buforze licząc końcówki linii ( \n) znaków - „l, --lines drukowania liczby nowej linii \ n \” - pochodzących zwc.c
Rahula Patila

@RahulPatil Większość implementacji robi znacznie więcej niż liczenie nowych linii. Zobacz przykład wymieniony w górnym komentarzu powyżej. To jest źródło wc używane w podstawowych narzędziach Linuksa.
Tonny,

tak .. widziałem to ... tylko wspomnę, ponieważ pytanie o wc -l... przepraszam ...
Rahul Patil

3

Witamy w świecie wolnego oprogramowania. Zawsze możesz spojrzeć na kod źródłowy

Chociaż muszę przyznać, że nie jestem programistą C, więc nie jestem tym, który tak naprawdę może wyjaśnić ci kod (i sam byłbym zainteresowany ).

Wiem, że ponieważ wc nie otwiera samego pliku, ale prosi system operacyjny, aby to zrobić, zależy to w dużej mierze od systemu operacyjnego i oczywiście od sposobu przechowywania pliku. Poza tym spodziewam się, że muszą istnieć prawidłowe praktyki programowania, np. Nie próbować odczytywać pliku jako całości na raz itp.


Co masz na myśli mówiąc „nie próbuję odczytać całego pliku na raz”?
detraveller

Mam na myśli ładowanie pliku do pamięci, powiedzmy, do pojedynczego ciągu / tablicy. W społeczności Perla nazywa się to slurping, i jest to szybkie i brudne rozwiązanie, które jest OK, gdy wiesz, że będziesz czytać kilka wierszy, ale podawanie naprawdę dużych plików do pamięci jednocześnie nie jest dobrym pomysłem.
Alois Mahdal

1
Z drugiej strony możesz odczytać, powiedzmy, 64 KiB, policzyć nowe wiersze i wyrzucić, powtórzyć ... W ten sposób zjesz co najwyżej 64 KiB, bez względu na to, jak duży jest ten plik. (To łatwiejsze, gdy zdasz sobie sprawę, że nowa linia może mieć 2 bajty, a tym samym zostać podzielona na 2 części; teraz na tym zaczyna się zabawa)
Alois Mahdal

Nie jest to zbyt ważne, ale: „ponieważ wc nie otwiera samego pliku, ale prosi system operacyjny, aby to zrobił” - nie jestem pewien, co przez to rozumiesz, ale wątpię, czy to prawda. Z pewnością sam odczytuje wszystkie postacie.
Arjan

2
@Arjan Chociaż, aby być naprawdę poprawnym: wykluczając systemy wbudowane, programy prawie tak naprawdę same nie czytają, sedno jądra i systemu operacyjnego polega na tym, że wykonuje to za nich. W rzeczywistości open (), close (), read () (Linux, Windows, gniazdo lub plik) to wszystkie wywołania systemowe, że rzeczywiste programy nie mają pojęcia o wewnętrznym działaniu.
Alois Mahdal
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.