Quando a contagem de linhas fornece resultados inesperados, devemos verificar se cada utilitário de processamento de texto entende o que uma linha é da mesma maneira. Isso geralmente se resume a duas perguntas:
1) Problemas de conversão de arquivos: Quais caracteres são usados como EOL (fim de linha aka nova linha ou quebra de linha)? Pode ser \r
, \n
ou \r\n
dependendo do SO.
2) A última linha também é terminada com o EOL? Se não, como os utilitários de processamento de texto lidam com isso?
Neste caso, a segunda questão estava levando a uma explicação.
O que o wc -l
conta?
Diretamente da página man:
-l, --lines print the newline counts
Obviamente, a última linha não é contada, se não for terminada com uma nova linha, ou seja, o resultado será um menor que o número real de linhas.
O que o grep
produz?
grep
termina cada linha de saída com uma nova linha. Eu não encontrei na documentação, só testei.
Agora podemos fazer um teste para explicar o comportamento descrito na pergunta:
- Vamos criar um arquivo de teste com 3 linhas, mas sem uma nova linha
echo -ne "first\nsecond\nthird" > 3lines.txt
- Vamos verificar o último caractere:
tail -1 3lines.txt | od -c
Ok, não '\ n'.
-
wc -l < 3lines.txt
A saída é: 2 (a última linha não foi contada, porque a última nova linha está ausente)
- Passe todas as linhas pelo grep
grep . < 3lines.txt | wc -l
A saída é 3 (todas as linhas são contadas, porque nenhuma nova linha está ausente)
- Filtre apenas uma linha (pode ser qualquer linha)
grep -v first < 3lines.txt | wc -l
A saída é 2 (novamente todas as linhas são contadas).