Como o `wc -l` funciona?

11

Preciso ler um arquivo grande e, antes de começar a ler, preciso saber o número total de linhas no arquivo (que estão em milhões).

Eu implementei muitas soluções e encontrei uma. Mas durante a minha pesquisa eu estava pensando em ver como wc -lfunciona. Não encontrei nada no Google.

Embora tenha encontrado uma solução para o meu problema, ainda gostaria de saber como wc -lfunciona, pois ele pode calcular o número de linhas de um arquivo com 92 milhões de linhas em alguns segundos!

Quão?

detraveller
fonte

Respostas:

20

Ele lê o arquivo inteiro e conta o número de terminações de linha. Contar terminações de linha é realmente barato; a maior parte do tempo gasto é lendo o arquivo. Se o arquivo estiver (principalmente) no cache do buffer, também será barato. Caso contrário, isso dependerá da velocidade do seu armazenamento de arquivos.

Em outras palavras, não há mágica.

rici
fonte
Ele lê o arquivo inteiro e conta o número de terminações de linha? Para chegar ao final da linha, ele basicamente não lê a linha inteira até chegar ao fim? E isso significaria ler o arquivo inteiro, certo?
detraveller
@detraveller: sim, ele lê o arquivo inteiro, como eu disse. Ele não lê linha por linha, ou todos de uma vez, mas lê todos os caracteres e conta quantos desses caracteres são caracteres de final de linha.
rici 9/07/2013
7

O WC apenas lê o arquivo em blocos de bytes brutos (preferencialmente em múltiplos do tamanho natural do bloco do sistema de arquivos subjacente no qual o arquivo está localizado).
Depois, ele apenas varre o buffer, contando os caracteres de final de linha. (Também conta espaços, tabulações, feeds de formulário e outros caracteres especiais, caso você deseje outras informações além da saída -l.)

A leitura do disco é a parte cara em termos de velocidade. A varredura do buffer leva um tempo negligenciável em comparação com isso.

Digamos que você tenha 90 milhões de linhas com, em média, 100 caracteres por linha.
Isso significa cerca de 9.000.000.000 caracteres ou cerca de 860 MB.
Um PC decente com uma unidade SATA-3Gb / s fará isso em menos de 10 segundos. Mesmo em um sistema de arquivos relativamente lento, com alguma outra atividade acontecendo ao mesmo tempo.
Uma máquina rápida com algum ajuste de desempenho e um sistema de arquivos otimizado pode fazê-lo em menos de 5 segundos, mesmo sem ter que recorrer ao SATA-6G e a uma unidade SSD.

Tonny
fonte
ele apenas verifica através do tampão contando o fim-de-linha ( \ncaracteres) - "-l, --lines imprimir as contagens de nova linha \ n \" - extraiu-se a partir dewc.c
Rahul Patil
@RahulPatil A maioria das implementações faz muito mais do que apenas contar novas linhas. Veja o exemplo mencionado no comentário superior acima. Essa é a fonte do wc, usada nos utilitários principais do Linux.
Tonny 12/07
sim .. Eu vi isso .. apenas menciono porque, pergunta sobre wc -l.. desculpe ...
Rahul Patil
3

Bem-vindo ao mundo do software livre. Você sempre pode olhar para o código fonte

Embora eu deva admitir que não sou programador em C, não sou o único que pode explicar o código para você (e eu também ficaria interessado ).

O que eu sei é que, como o wc não abre o arquivo em si, mas pede ao SO para fazê-lo, isso depende muito do SO e, é claro, de como o arquivo é armazenado. Além disso, eu esperaria que práticas de programação corretas devessem estar em vigor, por exemplo, não tentando ler o arquivo como um todo de uma só vez, etc.

Alois Mahdal
fonte
O que você quer dizer com 'não tentar ler o arquivo inteiro de uma vez'?
detraveller
Quero dizer, carregar o arquivo na memória, digamos, em uma única string / array. Na comunidade Perl, isso é chamado de slurping, e é uma solução rápida e suja, que é boa quando você sabe que lerá algumas linhas, mas alimentar arquivos realmente grandes na memória de uma só vez raramente é uma boa idéia.
Alois Mahdal
11
Por outro lado, você pode ler, digamos, 64 KiB, contar novas linhas e jogá-la fora, repita ... Dessa forma, você consumirá algo acima de 64 KiB, no máximo, não importa o tamanho do arquivo. (É menos fácil quando você percebe que nova linha pode ter 2 bytes e dividir-se assim entre 2 pedaços; agora é aí que a diversão começa)
Alois Mahdal
Não é muito importante, mas: "como o wc não abre o arquivo em si, mas pede que o SO faça" - não sei o que você quer dizer com isso, mas duvido que esteja correto. Certamente está lendo todos os personagens por si só.
Arjan 8/13
2
@ Arjan Embora, para ser realmente correto: excluindo os sistemas incorporados, os programas dificilmente façam a leitura, o ponto principal do Kernel e do SO é que ele faz o trabalho para eles. De fato, abrir (), fechar (), ler () (seja Linux, Windows, soquete ou arquivo) são todas chamadas de sistema que os programas atuais não têm idéia do funcionamento interno.
Alois Mahdal