Recherche binaire dans un fichier texte trié

13

J'ai un gros fichier trié avec des milliards de lignes de longueurs variables. Étant donné une nouvelle ligne, je voudrais savoir quel numéro d'octet il obtiendrait s'il avait été inclus dans le fichier trié.

Exemple

a\n
c\n
d\n
f\n
g\n

Étant donné l'entrée 'foo', j'obtiendrais la sortie 9.

C'est facile à faire en parcourant tout le fichier, mais étant des milliards de lignes de longueurs variables, il serait plus rapide de faire une recherche binaire.

Un tel outil de traitement de texte existe-t-il déjà?

Éditer:

Il le fait maintenant: https://gitlab.com/ole.tange/tangetools/blob/master/bsearch/bsearch

Ole Tange
la source
combien de temps est la ligne que vous recherchez (en caractères)? et combien de ces lignes devez-vous rechercher?
gogoud
@gogoud Je ne cherche pas un outil limité, mais un qui fonctionne sur n'importe quel fichier texte (peu importe la longueur de ligne ou le nombre de lignes).
Ole Tange
pour ceux qui aimeraient générer une telle entrée gigantesque: unix.stackexchange.com/a/279098/9689
Grzegorz Wierzowiecki

Réponses:

4

Je ne suis pas au courant d'un outil standard faisant cela. Cependant, vous pouvez écrire le vôtre. Par exemple, le script ruby ​​suivant devrait faire le travail.

file, key = ARGV.shift, ARGV.shift
min, max = 0, File.size(file)

File.open(file) do |f|
  while max-min>1 do
    middle = (max+min)/2
    f.seek middle
    f.readline
    if f.eof? or f.readline>=key
      max = middle
    else
      min = middle
    end
  end
  f.seek max
  f.readline
  p f.pos+1
end

C'est un peu délicat car après la recherche, vous êtes généralement au milieu d'une ligne et devez donc faire une ligne de lecture pour arriver au début de la ligne suivante, que vous pouvez lire et comparer à votre clé.

michas
la source
Peut-il être modifié pour accepter -n / -r pour traiter les fichiers triés par sort -ret sort -n?
Ole Tange
Le code ci-dessus est principalement pour montrer l'idée. C'est loin d'être parfait. (Par exemple, il échoue si la clé passe à la première place.) N'hésitez pas à vous adapter à vos besoins.
michas
5

(Ce n'est pas une bonne réponse à votre question, juste un point de départ.)

J'ai utilisé sgrep (grep trié) dans une situation similaire.

Malheureusement (nous avons besoin de l'état actuel), il n'a pas de sortie à décalage d'octet; mais je pense que cela pourrait être facilement ajouté.

JJoao
la source