web-dev-qa-db-fra.com

Comptez le nombre de lignes vierges à la fin du fichier

J'ai un fichier avec des lignes vides à la fin du fichier. Puis-je utiliser grep pour compter le nombre de lignes vierges à la fin du fichier avec le nom du fichier étant passé comme variable dans le script?

11

Si les lignes vides sont seulement à la fin

grep  -c '^$' myFile

ou:

grep -cx '' myFile
11
bu5hman

Juste pour le plaisir, de Spooky sed:

#!/bin/sh
sed '/./!H;//h;$!d;//d;x;s/\n//' "$1" | wc -l

Explication:

  • /./ traite des lignes avec n'importe quel caractère, alors /./! traite des lignes non vides; Pour ceux-ci, la commande H appendez-les à l'espace de maintien. Ainsi, si pour chaque ligne vide, nous avons ajouté une ligne à l'espace de maintien, il y a toujours une ligne de plus que le nombre de lignes vides. Nous allons nous en soucier plus tard.
  • //h Le motif vide correspond à la dernière expression régulière, qui était n'importe quel caractère, de sorte que toute ligne non vide est adressée et déplacée vers l'espace de maintien par la commande h à "réinitialiser" Les lignes collectées à 1. Lorsque la prochaine ligne vide sera annexée, il y aura deux à nouveau, comme prévu.
  • $!d arrête le script sans sortie pour toutes les dernières lignes, de sorte que d'autres commandes ne sont exécutées que après la dernière ligne. Donc, quelles que soient les lignes vides que nous avons collectées dans l'espace de maintien sont à la fin du fichier. Bon.
  • //d: La commande d est à nouveau exécutée pour des lignes non vides uniquement. Donc, si la dernière ligne n'était pas vide, sed _ quittera sans aucune sortie. Zéro lignes. Bon.
  • x Les échanges contiennent des espaces d'espace et des motifs, de sorte que les lignes collectées sont dans l'espace motivé à traiter maintenant.
  • Mais nous nous souvenons qu'il y a trop de lignes, alors nous le réduisons en supprimant une nouvelle ligne avec s/\n//.
  • VOILÀ! Le nombre de lignes correspond au nombre de lignes vides à la fin (note que la première ligne ne sera pas vide, mais qui se soucie), afin que nous puissions les compter avec wc -l.
11
Philippos

Un peu plus GNU tac/tail -r options:

tac file | awk 'NF{exit};END{print NR?NR-1:0}'

Ou:

tac file | sed -n '/[^[:blank:]]/q;p' | wc -l

Notez que sur la sortie de:

printf 'x\n '

C'est là, où il y a un espace supplémentaire après la dernière ligne complète (que certains pouvaient considérer comme une ligne vierge supplémentaire, mais par la définition de texte POSIX, n'est pas un texte valide), celles-ci donneraient 0.

POSIXY:

awk 'NF{n=NR};END{print NR-n}' < file

mais cela signifie lire le fichier en totalité (tail -r/tac _ lirait le fichier en arrière à partir de la fin des fichiers déséquilibrés). Ça donne 1 sur la sortie de printf 'x\n '.

8
Stéphane Chazelas

Comme vous vous demandez réellement une solution grep solution J'appo que celui-ci ne s'appuyant que sur GNU _ _ grep (d'accord, également à l'aide de la syntaxe Shell et echo ...):

#!/bin/sh
echo $(( $(grep -c "" "$1") - $(grep -B$(grep -cv . "$1") . "$1" |grep -c "") ))

Qu'est ce que je fais ici? $(grep -c ".*" "$1") compte toutes les lignes du fichier, puis nous ajoutons le fichier sans les lignes vides de fuite.

Et comment obtenir ceux-ci? $(grep -B42 . "$1" serait grep toutes les lignes non vides et 42 lignes devant eux, de sorte qu'il imprimerait tout jusqu'à la dernière ligne non vide, tant qu'il n'existe pas plus de 42 lignes vides consécutives avant une ligne non vide. Pour éviter cette limite, je prends $(grep -cv . "$1") comme paramètre de l'option -B, qui est le nombre total de lignes vides, donc toujours assez grandes. De cette façon, j'ai supprimé les lignes vides de fin et peut utiliser |grep -c ".*" pour compter les lignes.

Brillant, n'est-ce pas? (-;

6
Philippos

Une autre solution awk. Cette variation réinitialise le compteur k chaque fois qu'il y a une ligne non vide. Ensuite, chaque ligne incrémente le compteur. (Ainsi, après la première ligne de longueur non vide, k==0.) À la fin, nous émettons le nombre de lignes que nous avons comptées.

Préparer le fichier de données

cat <<'X' >input.txt
aaa

bbb
ccc



X

Compter les lignes blanches de fuite dans l'échantillon

awk 'NF {k=-1}; {k++}; END {print k+0}' input.txt
3

Dans cette définition, une ligne vierge peut contenir des espaces ou d'autres caractères vides; C'est toujours vide. Si vous voulez vraiment compter des lignes vides plutôt que des lignes vierges, changez NF pour $0 != "".

5
roaima

pour compter le nombre de lignes vierges consécutives à la fin du fichier

Solide awk + tac Solution:

Échantillon input.txt:

$ cat input.txt
aaa

bbb
ccc



$  # command line 

L'action:

awk '!NF{ if (NR==++c) { cnt++ } else exit }END{ print int(cnt) }' <(tac input.txt)
  • !NF - assure la ligne de courant est vide (n'a pas de champs)
  • NR==++c - Assurer l'ordre consécutif des lignes vierges. (NR - numéro d'enregistrement, ++c - Compteur auxiliaire uniformément incrémenté)
  • cnt++ - compteur de lignes vierges

Le résultat:

3
2
RomanPerekhrest

IIUC, le script suivant appelé count-blank-at-the-end.sh ferait le travail:

#!/usr/bin/env sh

count=$(tail -n +"$(grep . "$1" -n | tail -n 1 | cut -d: -f1)" "$1" | wc -l)
num_of_blank_lines=$((count - 1))

printf "%s\n" "$num_of_blank_lines"

Exemple d'utilisation:

$ ./count-blank-at-the-end.sh FILE
4

Je l'ai testé en GNU bash, Android mksh et dans ksh.

1
Arkadiusz Drabczyk

Alternative Python Solution:

Exemple d'entrée.txt:

$ cat input.txt
aaa

bbb
ccc



$  # command line 

L'action:

python -c 'import sys, itertools; f=open(sys.argv[1]);
lines=list(itertools.takewhile(str.isspace, f.readlines()[::-1]));
print(len(lines)); f.close()' input.txt

Le résultat:

3

https://docs.python.org/3/library/itétools.html?highlight=itertools#itertools.takewhile

0
RomanPerekhrest