Как работает `wc -l`?

11

Я должен прочитать большой файл, и прежде чем я начну его читать, мне нужно знать общее количество строк в файле (в миллионах).

Я реализовал много решений и нашел одно. Но во время поисков я подумал посмотреть, как wc -lработает. Я не смог ничего найти в Google.

Хотя я нашел решение своей проблемы, я все же хотел бы знать, как это wc -lработает, так как он может рассчитать количество строк файла с 92 миллионами строк за несколько секунд!

Как?

detraveller
источник

Ответы:

20

Он читает весь файл и считает количество концов строки. Подсчет концов строк действительно дешев; большая часть времени тратится на чтение файла. Если файл окажется (в основном) в буферном кеше, это тоже будет дешево. В противном случае это будет зависеть от скорости вашего файлового хранилища.

Другими словами, нет волшебства.

RICi
источник
Он читает весь файл и считает количество концов строк? Чтобы добраться до конца строки, разве он не читает всю строку до конца? И это будет означать, что он прочитал весь файл, верно?
detraveller
@detraveller: да, он читает весь файл, как я уже сказал. Он не читает его построчно или все сразу, но читает каждый символ и считает, сколько из этих символов являются символами конца строки.
Ричи
7

WC просто читает файл в блоках необработанных байтов (предпочтительно в кратных натурального размера блока базовой файловой системы, в которой находится файл).
Затем он просто просматривает буфер, считая символы конца строки. (Он также подсчитывает пробелы, вкладки, каналы и другие специальные символы, на тот случай, если вам нужна другая информация, кроме вывода -l.)

Чтение с диска является дорогостоящей частью с точки зрения скорости. Сканирование буфера занимает незначительное время по сравнению с этим.

Скажем, у вас 90 миллионов строк, в среднем по 100 символов в строке.
Это около 9 000 000 000 символов или около 860 МБ.
Приличный ПК с диском SATA-3Gb / s сделает это менее чем за 10 секунд. Даже на относительно медленной файловой системе, где одновременно происходит какая-то другая деятельность.
Быстрая машина с некоторой настройкой производительности и оптимизированной файловой системой может сделать это менее чем за 5 секунд, даже не прибегая к SATA-6G и SSD-накопителю.

Tonny
источник
он просто просматривает буфер, считая \nсимволы конца строки ( ) - "-l, --lines печатает счетчик новой строки \ n \" - извлечено изwc.c
Rahul Patil
@RahulPatil Большинство реализаций делают намного больше, чем просто подсчитывают переводы строки. Смотрите пример, упомянутый в верхнем комментарии выше. Это источник wc, используемый в основных утилитах Linux.
Тонни
да .. я видел это .. просто я упоминаю, потому что, вопрос о wc -l.. извините ...
Рахул Патил
3

Добро пожаловать в мир свободного программного обеспечения. Вы всегда можете посмотреть на исходный код

Хотя я должен признать, что я не программист на Си, поэтому я не тот, кто действительно может объяснить код для вас (и я был бы заинтересован сам).

Что я знаю, так это то, что wc не открывает сам файл, а просит ОС сделать это, во многом это зависит от ОС и, конечно, от того, как файл хранится. Кроме того, я ожидаю, что должны быть правильные методы программирования, например, не пытаться прочитать файл целиком и т. Д.

Алоис Махдал
источник
Что вы имеете в виду, говоря «не пытаться прочитать весь файл сразу»?
detraveller
Я имею в виду загрузку файла в память, скажем, в одну строку / массив. В сообществе Perl это называется slurping, и это быстрое и грязное решение, которое хорошо, когда вы знаете, что будете читать несколько строк, но подача действительно большого файла в память редко бывает хорошей идеей.
Алоис Махдал
1
С другой стороны, вы можете читать, скажем, 64 КиБ, считать новые строки и выбрасывать их, повторять ... Таким образом, вы съедаете максимум 64 КБ, независимо от размера файла. (Это не так просто, когда вы понимаете, что символ новой строки может иметь 2 байта и, таким образом, разделиться на 2 блока; вот где начинается самое интересное)
Алоис Махдал,
Не слишком важно, но: «поскольку wc не открывает сам файл, а просит ОС сделать это» - не уверен, что вы подразумеваете под этим, но я сомневаюсь, что это правильно. Конечно, он читает все символы сам по себе.
Арджан
2
@Arjan Хотя, если быть точным: за исключением встроенных систем, программы практически не читают сами, весь смысл ядра и ОС состоит в том, что он выполняет свою работу за них. Фактически open (), close (), read () (будь то Linux, Windows, сокет или файл) - это все системные вызовы, которые в реальных программах не имеют представления о внутренней работе.
Алоис Махдал