J'aimerais savoir s'il y a un conseil à faire grep
aussi vite que possible. J'ai une assez grande base de fichiers texte à rechercher le plus rapidement possible. Je les ai toutes réduites en minuscules pour pouvoir me débarrasser de -i
option. Cela rend la recherche beaucoup plus rapide.
En outre, j'ai découvert que -F
et -P
modes sont plus rapides que le mode par défaut. J'utilise le premier lorsque la chaîne de recherche n'est pas une expression régulière (texte brut), le dernier si regex est impliqué.
Quelqu'un at-il une expérience dans l'accélération de grep
? Peut-être le compiler à partir de rien avec un drapeau particulier (je suis sous Linux CentOS), organiser les fichiers d'une certaine manière ou peut-être rendre la recherche parallèle d'une certaine manière?
Essayez avec GNU parallel , qui inclut n exemple d'utilisation avec grep
:
grep -r
_ greps récursivement dans les répertoires. Sur les CPU multicœurs GNUparallel
peut souvent accélérer cela.find . -type f | parallel -k -j150% -n 1000 -m grep -H -n STRING {}
Cela exécutera 1,5 tâche par cœur et donnera 1000 arguments à
grep
.
Pour les gros fichiers, il peut diviser l’entrée en plusieurs morceaux avec le --pipe
et --block
arguments:
parallel --pipe --block 2M grep foo < bigfile
Vous pouvez également l'exécuter sur plusieurs machines différentes via SSH (ssh-agent nécessaire pour éviter les mots de passe):
parallel --pipe --sshlogin server.example.com,server2.example.net grep foo < bigfile
Si vous recherchez des fichiers très volumineux, il peut être très utile de définir vos paramètres régionaux.
GNU grep va beaucoup plus vite dans les paramètres régionaux C qu'avec UTF-8.
export LC_ALL=C
Ripgrep prétend maintenant être le plus rapide.
https://github.com/BurntSushi/ripgrep
Inclut également le parallélisme par défaut
-j, --threads ARG
The number of threads to use. Defaults to the number of logical CPUs (capped at 6). [default: 0]
Du README
Il est construit sur le moteur regex de Rust. Le moteur regex de Rust utilise des automates finis, SIMD et des optimisations littérales agressives pour rendre la recherche très rapide.
Apparemment, utiliser --mmap peut aider sur certains systèmes:
http://lists.freebsd.org/pipermail/freebsd-current/2010-August/019310.html
Ce n'est pas strictement une amélioration de code, mais quelque chose que j'ai trouvé utile après avoir exécuté grep sur plus de 2 millions de fichiers.
J'ai déplacé l'opération sur un disque SSD bon marché (120 Go). À environ 100 USD, c'est une option abordable si vous traitez régulièrement de nombreux fichiers.
Si vous ne vous souciez pas des fichiers contenant la chaîne, vous pouvez séparer lecture et grepping en deux travaux, car il peut être coûteux de générer grep
plusieurs fois - une fois pour chaque petit fichier.
Si vous avez un très gros fichier:
parallel -j100% --pipepart --block 100M -a <very large SEEKABLE file> grep <...>
Beaucoup de petits fichiers compressés (triés par inode)
ls -i | sort -n | cut -d' ' -f2 | fgrep \.gz | parallel -j80% --group "gzcat {}" | parallel -j50% --pipe --round-robin -u -N1000 grep <..>
Je compresse généralement mes fichiers avec lz4 pour un débit maximal.
Si vous voulez juste le nom du fichier avec la correspondance:
ls -i | sort -n | cut -d' ' -f2 | fgrep \.gz | parallel -j100% --group "gzcat {} | grep -lq <..> && echo {}
En me basant sur la réponse de Sandro, j’ai examiné la référence qu’il a fournie ici et j’ai joué avec BSD grep contre GNU grep. Mes résultats rapides ont montré: GNU grep est beaucoup, beaucoup plus rapide.
Donc, ma recommandation à la question initiale "grep le plus rapide possible": Assurez-vous que vous utilisez GNU grep plutôt que BSD grep (qui est la valeur par défaut sous MacOS, par exemple).
Personnellement, j'utilise ag (recherche d'argent) au lieu de grep et c'est beaucoup plus rapide. Vous pouvez également le combiner avec un bloc parallèle et un bloc de tuyaux.
https://github.com/ggreer/the_silver_searcher
Mise à jour: J'utilise maintenant https://github.com/BurntSushi/ripgrep , qui est plus rapide que ag en fonction de votre cas d'utilisation.
Une chose que j'ai trouvée plus rapide pour utiliser grep dans la recherche (en particulier pour changer de modèle) dans un seul fichier volumineux consiste à utiliser split + grep + xargs avec son drapeau parallèle. Par exemple:
Avoir un fichier d'identifiants que vous souhaitez rechercher dans un gros fichier appelé my_ids.txt Nom de bigfile bigfile.txt
Utilisez split pour scinder le fichier en plusieurs parties:
# Use split to split the file into x number of files, consider your big file
# size and try to stay under 26 split files to keep the filenames
# easy from split (xa[a-z]), in my example I have 10 million rows in bigfile
split -l 1000000 bigfile.txt
# Produces output files named xa[a-t]
# Now use split files + xargs to iterate and launch parallel greps with output
for id in $(cat my_ids.txt) ; do ls xa* | xargs -n 1 -P 20 grep $id >> matches.txt ; done
# Here you can tune your parallel greps with -P, in my case I am being greedy
# Also be aware that there's no point in allocating more greps than x files
Dans mon cas, cela réduisait ce qui aurait été un travail de 17 heures en un travail de 1 heure et 20 minutes. Je suis sûr qu'il existe une sorte de courbe en cloche sur l'efficacité et qu'il est évident que passer en revue les cœurs disponibles ne vous sera d'aucun bien, mais c'était une bien meilleure solution que tous les commentaires ci-dessus pour mes besoins, comme indiqué ci-dessus. Cela présente un avantage supplémentaire par rapport au script parallèle en utilisant principalement des outils natifs (linux).
cgrep, s'il est disponible, peut être beaucoup plus rapide que grep.
MCE 1.508 inclut un script d'encapsuleur {fichier, liste} de niveau chunk double prenant en charge de nombreux binaires C; consentp, grep, egrep, fgrep et tre-consentp.
https://metacpan.org/source/MARIOROY/MCE-1.509/bin/mce_grep
https://metacpan.org/release/MCE
Il n'est pas nécessaire de convertir en minuscules pour vouloir que -i s'exécute rapidement. Passez simplement --lang = C à mce_grep.
L'ordre de sortie est préservé. Les sorties -n et -b sont également correctes. Malheureusement, ce n'est pas le cas pour GNU parallèle mentionné sur cette page. J'espérais vraiment GNU Parallèle pour fonctionner ici. De plus, mce_grep le fait pas sous-shell (sh-c/chemin/à/grep) lors de l'appel du binaire.
Une autre alternative est le module MCE :: Grep inclus avec MCE.
Un léger écart par rapport au sujet initial: les utilitaires de ligne de commande de recherche indexés du projet googlecodesearch sont bien plus rapides que grep: https://github.com/google/codesearch :
Une fois que vous l'avez compilé (le paquetage golang est nécessaire), vous pouvez indexer un dossier avec:
# index current folder
cindex .
L'index sera créé sous ~/.csearchindex
Maintenant, vous pouvez rechercher:
# search folders previously indexed with cindex
csearch eggs
Je continue de passer les résultats dans grep pour obtenir des correspondances colorisées.