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

2007
detraveller

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

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

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

Как?

9
http://lingrok.org/xref/coreutils/src/wc.c Arjan 10 лет назад 5

3 ответа на вопрос

19
rici

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

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

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

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

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

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

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

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

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

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

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

Похожие вопросы