Comment puis-je compter le nombre de lignes dans un fichier après une correspondance grep?

14

J'essaie de compter le nombre de lignes après une ligne problématique dans un fichier csv. Je sais que je peux utiliser la grep -a #syntaxe pour afficher # nombre de lignes après qu'une correspondance a été trouvée. Je ne m'intéresse qu'au nombre réel de lignes. Je me rends compte que je pourrais définir le nombre à MAX_INT, le canaliser dans un fichier et faire un peu plus de traitement.

Je suis à la recherche d'un one-liner succinct pour me dire le nombre.

Aucune suggestion?

NathanChristie
la source

Réponses:

15
{ grep -m1 match; grep -c ''; } <file

Cela fonctionnera avec GNU grepet un lseek()infile capable. Le premier greps'arrêtera à 1 -match, et le second comptera -cchaque ligne restante en entrée.

Sans GNU grep:

{ sed '/match/q'; grep -c ''; } <file

Bien sûr, w / grepvous pouvez utiliser n'importe laquelle / toutes ses autres options en plus, et l'arrêt d'un match n'est pas du tout nécessaire.

mikeserv
la source
Les deux impriment également la ligne, et la seconde sur imprime jusqu'à la première correspondance, puis 0 pour moi?
123
@ User112638726 - vous pouvez grep -m1 match >/dev/nullbien sûr supprimer l'impression du premier match . Et votre deuxième problème est un GNU sed- il ne réinitialise pas son décalage d'entrée par spécification. Vous devez utiliser -uw / GNU - ce qui n'est pas toujours souhaitable. J'aurais pu être plus clair, mais mon hypothèse était qu'un GNU grepet GNU sedviendraient par paires. Je pense que, aussi, grep -qm1pourrait fonctionner pour raccourcir la /dev/nullredirection - mais GNU grepfait des choses étranges avec -qet je ne me souviens pas comment ces deux fonctionnent ensemble.
mikeserv
1
Belle réponse - démontre vraiment la puissance des groupements de commandes. Je ne sais pas avec certitude, mais je suppose que wc -lc'est un peu moins cher que grep -c ''.
Digital Trauma
1
@DigitalTrauma - Oui, je l'ai considéré (rétrospectivement) , mais je l'avais déjà écrit, et ça rimait presque, alors j'ai pensé que je laisserais assez bien tranquille. Et de toute façon, tu l'as dit aussi, alors je vais dormir tranquille maintenant.
mikeserv
9

Voici une façon.

$ cat foo
aaa
bbb
ccc
ddd
eee
fff
$ awk '/^ddd/{a=FNR}END{print FNR-a}' foo
2
$
Steve
la source
4
ce n'est pas du codegolf, pouvez-vous donner des détails (FNR, END, etc.)?
Archemar
3
Sûr. awk utilise FNR pour identifier le numéro d'enregistrement d'entrée. END est le code exécuté à la fin du fichier. Ainsi, lorsqu'une correspondance est trouvée, le numéro d'enregistrement actuel est enregistré. À la fin du fichier, ce nombre est ensuite soustrait du nombre total de lignes dans le fichier.
steve
1
Peut aussi bien utiliser NR car il s'agit d'un seul fichier.
123
6

Une autre façon - l'utilisation de dcest un peu ésotérique, mais semble bien fonctionner ici:

sed -n '/problem/=;$=' prob.txt | dc -e '??r-p'

sedrecherche prob.txt«problème» et la dernière ligne et utilise la =commande pour afficher le numéro de ligne des deux.

dc lit ces deux valeurs sur la pile, les inverse, soustrait et imprime la différence.

Traumatisme numérique
la source
5

Entièrement avec sed (bien que deux commandes avec un tuyau)

sed '/ddd/,$!d' file | sed -n '$='

Supprime toute la ligne avant la ligne, puis la commande suivante compte les lignes du nouveau fichier.

123
la source
3

Cela devrait supprimer toutes les lignes jusqu'à (et y compris) la ligne problématique, puis compter les lignes restantes:

sed '1,/problem/d' data.txt | wc -l
client
la source
1
(en supposant que "problème" n'est pas sur la première ligne)
Stéphane Chazelas