J'ai un gros fichier contenant une chaîne sur chaque ligne. J'aimerais pouvoir déterminer rapidement si une chaîne est dans le fichier. Idéalement, cela serait fait en utilisant un algorithme de type binaire chop.
Certains utilisateurs de Google ont révélé la commande look
avec l'indicateur -b
qui promet de localiser et d'afficher toutes les chaînes commençant par un préfixe donné à l'aide d'un algorithme de recherche binaire. Malheureusement, cela ne semble pas fonctionner correctement et renvoie des résultats nuls pour les chaînes que je connais sont dans le fichier (elles sont correctement renvoyées par l'équivalent grep
search).
Est-ce que quelqu'un connaît un autre utilitaire ou une autre stratégie pour effectuer une recherche efficace dans ce fichier?
Il y a une différence essentielle entre grep
et look
:
Sauf indication contraire explicite, grep
trouvera des motifs même quelque part dans les lignes. Pour look
, la page de manuel indique:
look - lignes d'affichage début avec une chaîne donnée
Je n'utilise pas très souvent look
, mais cela a bien fonctionné avec un exemple trivial que je viens d'essayer.
Peut-être une réponse un peu tardive:
Sgrep va vous aider.
Sgrep (grep trié) recherche dans les fichiers d'entrée triés les lignes correspondant à une clé de recherche et génère les lignes correspondantes. Lors de la recherche de gros fichiers, sgrep est beaucoup plus rapide que grep Unix traditionnel, mais avec des restrictions importantes.
Vous pouvez télécharger la source ici: https://sourceforge.net/projects/sgrep/?source=typ_redirect
et les documents ici: http://sgrep.sourceforge.net/
Autrement:
Je ne sais pas quelle est la taille du fichier. Peut-être devriez-vous essayer parallèlement:
https://stackoverflow.com/questions/9066609/fastest-possible-grep
Je fais toujours grep avec des fichiers dont la taille> 100 Go, ça marche bien.
Si vous le voulez vraiment rapide (O (1) rapide), vous pouvez construire un ensemble de hachage à examiner. Je ne pouvais pas trouver une implémentation qui me permettrait de stocker un hachage pré-construit dans un fichier et de le tester sans sans avoir à lire le fichier entier dans mémoire, donc j'ai roulé le mien .
Construire le hash set (-b
/--build
):
./hashset.py --build string-list.txt strings.pyhashset
Analyser le hash set (-p
/--probe
):
./hashset.py --probe strings.pyhashset \
'Is this string in my string list?' 'What about this one?'
… Ou avec une chaîne pour rechercher sur une entrée standard:
printf '%s\n' 'Is this string in my string list?' 'What about this one?' |
./hashset.py --probe strings.pyhashset
Vous pouvez désactiver la sortie de --probe
avec l'option -q
/--quiet
si le statut de sortie ne vous intéresse que:
if ./hashset.py --quiet --probe strings.pyhashset ...; then
echo 'Found'
else
echo 'Not found'
fi
Pour plus d'options, voir la description d'utilisation accessible via l'option -h
/--help
ou le fichier README
qui l'accompagne.
sgrep pourrait fonctionner pour vous:
Sudo apt-get install sgrep
sgrep -l '"needle"' haystack.txt
La page du projet http://sgrep.sourceforge.net/ dit:
Sgrep utilise un algorithme de recherche binaire, qui est très rapide, mais nécessite une entrée triée.
Pour l'insertion cependant, je pense qu'il n'y a pas de meilleure solution que d'utiliser une base de données: https://stackoverflow.com/questions/10658380/Shell-one-liner-to-add-a-line-to -a-Sorted-File/33859372 # 33859372
Vous pouvez déchiqueter le fichier en morceaux puis grep le morceau que vous vouliez:
for line in $(cat /usr/share/dict/american-english | tr '[:upper:]' '[:lower:]' | sort | uniq)
do
prefix=$(echo $line | md5sum - | cut -c 1-2)
mkdir -p $prefix
echo $line | gzip >> $prefix/subwords
done
alors la recherche ressemblerait à ceci:
prefix=$(echo $Word | md5sum - | cut -c 1-2)
zgrep -m 1 -w Word $prefix/subwords
Cela fait deux choses: