J'ai un fichier avec des lignes vides à la fin du fichier. Puis-je utiliser grep
pour compter le nombre de lignes vides à la fin du fichier avec le nom de fichier transmis comme variable dans le script?
text-processing
grep
wc
Raghunath Choudhary
la source
la source
grep
@MichaelJohn gagne pour la pureté dans mon livre.Réponses:
Si les lignes vides ne sont qu'à la fin
ou:
la source
grep -cv . myFile
est une autre façon de l'écrire (pour les golfeurs de code). Mais j'ai trouvé une solution avecgrep
s'il y a des lignes vides n'importe où dans le fichier.grep -cv .
compterait également les lignes qui ne contiennent que des octets qui ne forment pas de caractères valides.Juste pour le plaisir, un peu effrayant
sed
:Explication:
/./
adresse les lignes avec n'importe quel caractère, donc/./!
les lignes non vides; pour ceux-ci, laH
commande les ajoute à l'espace d'attente. Ainsi, si pour chaque ligne vide nous avons ajouté une ligne à l'espace d'attente, il y a toujours une ligne de plus que le nombre de lignes vides. Nous nous en occuperons plus tard.//h
le modèle vide correspond à la dernière expression régulière, qui était n'importe quel caractère, donc toute ligne non vide est adressée et déplacée vers l'espace d'attente par lah
commande pour "réinitialiser" les lignes collectées à 1. Lorsque la prochaine ligne vide sera ajoutée, il y en aura encore deux, comme prévu.$!d
arrête le script sans sortie pour toutes les lignes sauf la dernière, de sorte que d'autres commandes ne sont exécutées qu'après la dernière ligne. Donc, quelles que soient les lignes vides que nous avons collectées dans l'espace d'attente se trouvent à la fin du fichier. Bien.//d
: Lad
commande est à nouveau exécutée uniquement pour les lignes non vides. Donc, si la dernière ligne n'était pas vide,sed
elle quittera sans aucune sortie. Zéro lignes. Bien.x
les échanges contiennent de l'espace et de l'espace de motif, de sorte que les lignes collectées sont maintenant dans l'espace de motif à traiter.s/\n//
.wc -l
.la source
Un peu plus GNU
tac
/tail -r
options:Ou:
Notez que sur la sortie de:
Autrement dit, là où il y a un espace supplémentaire après la dernière ligne complète (que certains pourraient considérer comme une ligne vierge supplémentaire, mais selon la définition POSIX du texte, n'est pas du texte valide), ceux-ci donneraient 0.
POSIX:
mais cela signifie lire le fichier en entier (
tail -r
/tac
lirait le fichier en arrière depuis la fin sur les fichiers recherchables). Cela donne1
sur la sortie deprintf 'x\n '
.la source
Comme vous demandez réellement une
grep
solution, j'ajoute celle-ci en se basant uniquement sur GNUgrep
(d'accord, en utilisant également la syntaxe shell etecho
...):Qu'est ce que je fais ici?
$(grep -c ".*" "$1")
compte toutes les lignes du fichier, puis nous soustrayons le fichier sans les lignes vides de fin.Et comment les obtenir?
$(grep -B42 . "$1"
grep toutes les lignes non vides et 42 lignes avant elles, donc il imprimerait tout jusqu'à la dernière ligne non vide, tant qu'il n'y a 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'-B
option, qui est le nombre total de lignes vides, donc toujours assez grand. De cette façon, j'ai supprimé les lignes vides de fin et je peux utiliser|grep -c ".*"
pour compter les lignes.Brillant, n'est-ce pas? (-;
la source
tac | grep
le premier non vide avec-m -A 42
, puis un moins. Je ne sais pas lequel est le plus efficace, mais vous pourriez aussiwc -l | cut -d' ' -f1
au lieu de saluer les lignes blanches?tac
,wc
etcut
, mais ici, j'ai essayé de me limitergrep
. Vous pouvez appeler cela de la perversité, je l'appelle du sport. (-;Une autre
awk
solution. Cette variation réinitialise le compteurk
chaque fois qu'il y a une ligne non vide. Ensuite, chaque ligne incrémente le compteur. (Donc, après la première ligne de longueur non vide,.k==0
) À la fin, nous affichons le nombre de lignes que nous avons comptées.Préparer le fichier de données
Comptez les lignes vides de fin dans l'échantillon
Dans cette définition, une ligne vierge peut contenir des espaces ou d'autres caractères vides; c'est encore vierge. Si vous voulez vraiment compter les lignes vides plutôt que les lignes vides, changez
NF
pour$0 != ""
.la source
$0 > ""
? Cette utilisationstrcoll()
serait moins efficace que celle$0 != ""
qui estmemcmp()
utilisée dans de nombreuses implémentations (POSIX l'exigeaitstrcoll()
cependant).$0 > ""
pourrait être différent de$0 != ""
. J'ai tendance à traiterawk
comme un opérateur "lent" de toute façon (de sorte que si je sais que j'ai un grand ensemble de données en entrée et que le traitement est critique en temps, je verrai ce que je peux faire pour réduire la quantitéawk
à traiter - je ont utilisé desgrep | awk
constructions dans de telles situations). Cependant, après avoir jeté un coup d'œil à ce que je suppose être la définition POSIX, je ne vois aucune référence à l'unstrcoll()
ou à l'autrememcmp()
. Qu'est-ce que je rate?strcoll()
== les chaînes doivent être comparées en utilisant la séquence de classement spécifique aux paramètres régionaux . Comparez avec l' édition précédente . C'est moi qui l'ai soulevé. Voir aussi austingroupbugs.net/view.php?id=963a <= b && a >= b
n'est pas forcément la même quea == b
. Aie!awk
oubash
(pour ses[[ a < b ]]
opérateurs) en_US.UTF-8 sur les systèmes GNU locales par exemple pour①
vs②
par exemple (pourbash
, aucune<
,>
,=
retourne vrai pour ceux). On peut dire que c'est un bug dans la définition de ces paramètres régionaux plus que dans bash / awkSolide
awk
+tac
solution:Échantillon
input.txt
:L'action:
!NF
- s'assure que la ligne actuelle est vide (sans champs)NR==++c
- assurer l'ordre consécutif des lignes vierges. (NR
- nombre record,++c
- compteur auxiliaire régulièrement incrémenté)cnt++
- compteur de lignes viergesLe résultat:
la source
IIUC, le script suivant appelé
count-blank-at-the-end.sh
ferait l'affaire:Exemple d'utilisation:
Je l' ai testé dans
GNU bash
,Android mksh
etksh
.la source
Python
Solution alternative :Exemple input.txt:
L'action:
Le résultat:
https://docs.python.org/3/library/itertools.html?highlight=itertools#itertools.take while
la source