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?
Si les lignes vides sont seulement à la fin
grep -c '^$' myFile
ou:
grep -cx '' myFile
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.s/\n//
.wc -l
.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 '
.
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? (-;
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 != ""
.
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
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
.
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