contar linhas em um arquivo

64

Tenho certeza de que há muitas maneiras de fazer isso: como posso contar o número de linhas em um arquivo de texto?

$ <cmd> file.txt
1020 lines
Chris Smith
fonte

Respostas:

98

A maneira padrão é with wc, que utiliza argumentos para especificar o que deve ser contado (bytes, caracteres, palavras, etc.); -lé para linhas:

$ wc -l file.txt
1020 file.txt
Michael Mrozek
fonte
Como conto as linhas de um arquivo se quero ignorar comentários? Especificamente, eu quero não contar linhas que começam com um +, algum espaço em branco (poderia haver espaço em branco) e, em seguida, um%, que é a forma como as linhas de comentário aparecer em um git diff de um arquivo MATLAB. Tentei fazer isso com grep, mas não consegui descobrir a expressão regular correta.
Gdalya
@Gdalya espero o seguinte gasoduto vai fazer isso (sem testes foram perfomed): cat matlab.git.diff | sed -e '/^\+[ ]*.*\%$/d' | wc -l. /regexp/dexclui uma linha se corresponder regexpe -eativa uma sintaxe adequada (IMNSHO) para regexp.
dbanet
2
Por que não simplesmente grep -v '^+ *%' matlab.git.diff | wc -l?
Celtschk 6/07
@celtschk, desde que isso seja usual nas linhas de comentários: é possível modificar seu grepcomando para considerar casos de comentários como " + Hello"(observe o (s) espaço (s) antes do +)?
Sopalajo de Arrierez
11
@SopalajodeArrierez: Claro que é possível: grep -v '^ *+' matlab.git.diff | wc -l(eu suponho que os sinais de cotação não foram feitos para fazer parte da linha; eu também assumo que ambas as linhas com e sem espaços à frente do +texto sejam comentários; se em menos, um espaço é obrigatório, substituir a estrela *com \+, ou apenas adicionar um outro espaço na frente da estrela). Provavelmente, em vez de corresponder apenas a espaços, convém corresponder a espaços em branco arbitrários; para isso substitua o espaço com [[:space:]]. Observe que também removi a correspondência de, %pois não está no seu exemplo.
Celtschk
15

Como Michael disse, wc -lé o caminho a percorrer. Mas, apenas no caso de você inexplicavelmente têm bash, perlou awk, mas não wc, aqui estão mais algumas soluções:

Apenas Bash

$ LINECT=0; while read -r LINE; do (( LINECT++ )); done < file.txt; echo $LINECT

Soluções Perl

$ perl -lne 'END { print $. }' file.txt

e o muito menos legível:

$ perl -lne '}{ print $.' file.txt

Solução Awk

$  awk 'END {print NR}' file.txt
Steven D
fonte
15

Steven D esqueceu o GNU sed:

sed -n '$=' file.txt

Além disso, se você quiser a contagem sem gerar o nome do arquivo e estiver usando wc:

wc -l < file.txt

Apenas para o inferno:

cat -n file.txt | tail -n 1 | cut -f1
Dennis Williamson
fonte
2
Ou grep -c '', ou tr -dc '\n' | wc -c, ou nl -ba -nln | tail -n 1 |sed -e 's/[^0-9].*//'... Alguma dessas opções é útil por si só (em oposição às coisas a serem construídas para criar um programa que faz mais do que contar linhas), além de wc -l(puro) (ba) sh?
Gilles 'SO- stop be evil'
11
@Gilles: Eu acho que a frase "muitas maneiras" na pergunta desencadeou um desafio que Steve e eu enfrentamos.
Dennis Williamson
11
@Gilles:sed 's/.*//' file.txt | uniq -c
Dennis Williamson
2
@Gilles: Oh, você quis dizer primeiro . uniq -c -w 0 file.txte você pode cut -c -7manter apenas o número. Ou, mais POSIXly: uniq -c file.txt | awk '{c+=$1}END{print c}'. Que tal dc(mesmo que não seja POSIX)? uniq -c file.txt | cut -c -7 | sed '$alax' | dc -e '[pq]sb[+z1=blax]sa' -. bcé POSIX: uniq -c file.txt | cut -c -7 | sed -n ':a;${s/\n/ + /gp;b};N;ba' | bc. A resposta fácil se você assumir um comprimento de linha limitada: uniq -c -f 100000 file.txt.
Dennis Williamson
11
@JosipRodin: Citações adicionadas
Dennis Williamson
11

Palavra de aviso ao usar

wc -l

porque wc -l funciona contando \ n, se a última linha do seu arquivo não terminar em uma nova linha efetivamente, a contagem da linha será desativada em 1. (daí a convenção antiga que deixa a nova linha no final do seu arquivo)

Como nunca posso ter certeza se algum arquivo segue a convenção de terminar a última linha com uma nova linha ou não, recomendo usar qualquer um desses comandos alternativos que incluirão a última linha na contagem, independentemente da nova linha ou não.

sed -n $= filename
perl -lne 'END { print $. }' filename
awk 'END {print NR}' filename
grep -c '' filename
pretzels1337
fonte
bom resumo. E bem-vindo para unix e linux
Sebastian
Hm, a última peça é realmente a linha?
Gena2x # 18/14
11
Tenho certeza de que depende do caso de todos; pois a 'última peça' geralmente é uma linha de texto que alguém não encerrou com uma nova linha. O caso de uso que encontro com mais frequência é um arquivo com uma única sequência de texto que não termina em uma nova linha. wc -l contaria isso como "0", quando eu esperaria uma contagem de "1".
precisa
3

Caso você tenha apenas o bash e absolutamente nenhuma ferramenta externa disponível, você também pode fazer o seguinte:

count=0
while read
do
  ((count=$count+1))
done <file.txt
echo $count

Explicação: o loop lê a entrada padrão linha por linha ( read; como não fazemos nada com a entrada de leitura de qualquer maneira, nenhuma variável é fornecida para armazená-la) e aumenta a variável a countcada vez. Devido ao redirecionamento ( <file.txtdepois done), a entrada padrão para o loop é de file.txt.

celtschk
fonte
2

Você sempre pode usar o comando da grepseguinte maneira:

grep -c "^" file.txt

Ele contará todas as linhas reais de file.txt, independentemente de sua última linha conter ou não um caractere LF no final.

Paolo
fonte