compter les lignes dans un fichier


65

Je suis sûr qu'il y a plusieurs façons de procéder: comment compter le nombre de lignes d'un fichier texte?

$ <cmd> file.txt
1020 lines

Réponses:


99

La méthode standard est avec wc, qui prend des arguments pour spécifier ce qu’elle doit compter (octets, caractères, mots, etc.); -lest pour les lignes:

$ wc -l file.txt
1020 file.txt

Comment compter les lignes d'un fichier si je veux ignorer les commentaires? Plus précisément, je souhaite ne pas compter les lignes commençant par un +, des espaces (sans aucun espace), puis un%, qui correspond à la manière dont les lignes de commentaire apparaissent dans un diff git d'un fichier MATLAB. J'ai essayé de le faire avec grep, mais je ne pouvais pas trouver la bonne expression régulière.
Gdalya

@Gdalya J'espère que le pipeline suivant le fera (aucun test n'a été perfomed): cat matlab.git.diff | sed -e '/^\+[ ]*.*\%$/d' | wc -l. /regexp/dsupprime une ligne si elle correspond regexpet -eactive une syntaxe adéquate (IMNSHO) pour regexp.
dbanet

2
Pourquoi pas simplement grep -v '^+ *%' matlab.git.diff | wc -l?
celtschk

@celtschk, aussi longtemps que cela est habituel dans les lignes de commentaires: est-il possible de modifier votre grepcommande afin de considérer comme des commentaires comme " + Hello"(notez les espaces avant +)?
Sopalajo de Arrierez

1
@SopalajodeArrierez: Bien sûr que c'est possible: grep -v '^ *+' matlab.git.diff | wc -l(je suppose que les signes de citation n'étaient pas censés faire partie de la ligne; je suppose également que les deux lignes avec et sans espace devant +sont destinées à être des commentaires; au moins un espace est obligatoire, remplacez l'étoile *par \+ou ajoutez simplement un autre espace devant l'étoile). Au lieu de ne faire correspondre que des espaces, vous souhaiterez probablement faire correspondre des espaces arbitraires; pour cela, remplacez l'espace par [[:space:]]. Notez que j'ai aussi supprimé la correspondance %car le n'est pas dans votre exemple.
celtschk

15

Comme Michael l'a dit, wc -lc'est la voie à suivre. Mais, au cas où vous avez inexplicablement bash, perlou awknon wc, voici quelques solutions:

Bash seulement

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

Solutions Perl

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

et le beaucoup moins lisible:

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

Awk Solution

$  awk 'END {print NR}' file.txt

15

Steven D a oublié GNU sed:

sed -n '$=' file.txt

Aussi, si vous voulez le nombre sans sortir le nom du fichier et que vous utilisez wc:

wc -l < file.txt

Juste pour le plaisir:

cat -n file.txt | tail -n 1 | cut -f1

2
Ou grep -c '', ou tr -dc '\n' | wc -c, ou nl -ba -nln | tail -n 1 |sed -e 's/[^0-9].*//'... Est-ce que l'un quelconque de ceux-ci est utile en soi (par opposition aux éléments sur lesquels s'appuyer pour créer un programme qui fait plus que compter les lignes), autre que wc -lpure (ba) sh?
Gilles, arrête de faire le mal '

1
@ Gilles: Je pense que l'expression "beaucoup de manières" dans la question a déclenché un défi auquel Steve et moi avons relevé le défi.
Dennis Williamson

1
@Gilles:sed 's/.*//' file.txt | uniq -c
Dennis Williamson

2
@ Gilles: Oh, tu voulais dire en premier . uniq -c -w 0 file.txtet vous pouvez cut -c -7ne garder que le nombre. Ou, plus POSIXly: uniq -c file.txt | awk '{c+=$1}END{print c}'. Pourquoi pas dc(même si ce n'est pas POSIX)? uniq -c file.txt | cut -c -7 | sed '$alax' | dc -e '[pq]sb[+z1=blax]sa' -. bcest Posix: uniq -c file.txt | cut -c -7 | sed -n ':a;${s/\n/ + /gp;b};N;ba' | bc. La réponse facile si vous assumez une longueur de ligne limitée: uniq -c -f 100000 file.txt.
Dennis Williamson

1
@JosipRodin: Citations ajoutées
Dennis Williamson

11

Mot d'avertissement lors de l'utilisation

wc -l

Parce que wc -l fonctionne en comptant \ n, si la dernière ligne de votre fichier ne se termine pas par une nouvelle ligne, le nombre de lignes sera désactivé de 1. (d'où l'ancienne convention laissant la nouvelle ligne à la fin de votre fichier).

Étant donné que je ne peux jamais être sûr qu'un fichier donné respecte la convention consistant à mettre fin à la dernière ligne avec une nouvelle ligne ou non, je vous recommande d'utiliser l'une de ces commandes de remplacement, qui inclura la dernière ligne dans le décompte, que la nouvelle ligne soit sélectionnée ou non.

sed -n $= filename
perl -lne 'END { print $. }' filename
awk 'END {print NR}' filename
grep -c '' filename

beau résumé. Et bienvenue à unix et linux
Sebastian le

Hm est la dernière pièce vraiment en ligne?
gena2x

1
Je suis sûr que cela dépend du cas d'utilisation de chacun; Le dernier élément est généralement une ligne de texte que quelqu'un n'a pas terminée avec une nouvelle ligne. Le cas d'utilisation que je rencontre le plus souvent est un fichier avec une seule chaîne de texte qui ne se termine pas par une nouvelle ligne. wc -l compterait ceci comme "0", alors que je m'attendrais sinon à un compte de "1".
bretzels1337

3

Si vous ne disposez que de bash et d’aucun outil externe, vous pouvez également procéder comme suit:

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

Explication: la boucle lit ligne par ligne les entrées standard ( read; puisque nous ne faisons rien de toute façon avec l'entrée de lecture, aucune variable n'est fournie pour la stocker) et augmente la variable à countchaque fois. En raison de la redirection ( <file.txtaprès done), l’entrée standard pour la boucle est de file.txt.


2

Vous pouvez toujours utiliser la commande grepcomme suit:

grep -c "^" file.txt

Il comptera toutes les lignes réelles de file.txt, que sa dernière ligne contienne ou non un caractère LF à la fin.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.