J'ai un fichier avec environ 30.000.000 lignes (Radius Accounting) et j'ai besoin de trouver le dernier match d'un modèle donné.
La commande:
tac accounting.log | grep $pattern
donne ce dont j'ai besoin, mais c'est trop lent car le système d'exploitation doit d'abord lire tout le fichier, puis l'envoyer au canal.
J'ai donc besoin de quelque chose de rapide capable de lire le fichier de la dernière ligne à la première.
la source
tac
, mon problème était que cela n’aiderait pas si vous ne l’utilisiez pas également,-m
car le fichier doit encore être lu en entier par deux programmes. Sinon, vous pouvez simplement rechercher toutes les occurrences et ne conserver que la dernière comme je le fais avectail -n 1
.grep -m
, cela devrait être assez efficace.grep -m
elle l'est. Le PO n'utilisait pas,-m
donc grep et tac traitaient le tout.awk
ligne?La raison pour laquelle
ne s’arrête pas au premier match à cause de la mise en mémoire tampon.
Normalement,
head -n 1
quitte après avoir lu une ligne. Donc,grep
devrait obtenir un SIGPIPE et quitter dès qu'il écrit sa deuxième ligne.Mais ce qui se passe, c’est que parce que sa sortie n’est pas transmise à un terminal,
grep
mémoire tampon. C'est-à-dire qu'il ne l'écrit pas tant qu'il n'a pas suffisamment accumulé (4096 octets dans mon test avec GNU grep).Cela signifie que vous
grep
ne quitterez pas avant d'avoir écrit 8192 octets de données, donc probablement pas mal de lignes.Avec GNU
grep
, vous pouvez le faire quitter plus tôt en utilisant le--line-buffered
mot qui lui dit d’écrire des lignes dès qu’elles sont trouvées, qu’elles soient ou non acheminées vers un terminal. Alorsgrep
serait alors sortir sur la deuxième ligne qu'il trouve.Mais avec GNU de
grep
toute façon, vous pouvez utiliser à la-m 1
place ce que @terdon a montré, ce qui est mieux car il se termine au premier match.Si vous n’êtes
grep
pas GNUgrep
, vous pouvez utilisersed
ouawk
remplacer. Maistac
étant une commande GNU, je doute que vous trouviez un système avectac
oùgrep
n’est pas GNUgrep
.Certains systèmes doivent
tail -r
faire la même chose que GNUtac
.Notez que, pour les fichiers normaux (à rechercher),
tac
et qu'ilstail -r
sont efficaces car ils lisent les fichiers à l'envers, ils ne les lisent pas entièrement en mémoire avant de les imprimer en arrière (comme le ferait l'approche @ slm outac
des fichiers non réguliers) .Sur les systèmes où ni
tac
nitail -r
sont disponibles, les seules options sont d'implémenter la lecture en arrière à la main avec des langages de programmation tels queperl
ou utiliser:Ou:
Mais ceux-ci signifient trouver toutes les correspondances et n'impriment que le dernier.
la source
Voici une solution possible qui trouvera l'emplacement de la première occurrence du motif à partir de la dernière:
Ceci utilise les
-s
et dont les-r
commutateurstac
sont les suivants:la source
En utilisant sed
Affichage des méthodes alternatives à l' @ bien la réponse de Terdon en utilisant
sed
:Exemples
Utiliser Perl
En bonus, voici une notation un peu plus facile en Perl à retenir:
Exemple
la source
sed
celui) susceptible d'être de plusieurs ordres de grandeur plus lent quegrep 5 | tail -n1
oused '/5/h;$!d;g'
. Il utilisera également potentiellement beaucoup de mémoire. Ce n'est pas beaucoup plus portable que vous utilisez toujours GNUgrep -m
.