2012-05-22 4 views
3

J'utilise Python pour lire un fichier au format suivant:fichier Relocaliser en arrière plusieurs lignes (python)

iter1
iter2
iter3
[n lignes de choses]
FLAG = valeur

iter1
iter2
iter3
iter4
i ter5
[n lignes de choses]
FLAG = valeur
etc ....

Je veux à la recherche FLAG, lisez cette valeur, puis revenir en arrière en arrière par des lignes « n » et lire la valeur de l'itération finale. Notez qu'il n'y a pas toujours le même nombre d'itérations. Le nombre de lignes 'n' est cohérent dans chaque fichier; Toutefois, ces lignes peuvent contenir des nombres d'octets différents, ce qui me pose problème pour l'utilisation de la fonction de recherche.

Je voudrais faire quelque chose comme ceci:

f = open(file) 
for i in f: 
    a = re.search('FLAG') 
    if a: 
      print a 
      spot=f.tell() #mark original spot 
      f.seek(-n,1) #rewind by n lines 
      b = re.search('iter') 
      print b 
      f.seek(spot) #return to FLAG line, continue to next data set 
+1

Pouvez-vous lire le fichier entier en mémoire ou est-il trop grand? –

Répondre

1

En supposant que votre « n lignes de choses » ne contiennent pas de lignes commençant par « iter », vous rend le problème beaucoup plus difficile qu'il est. Tout ce que vous devez faire est de garder une trace de la dernière ligne que vous avez vu qui a commencé avec "iter". Puis quand vous voyez "FLAG =" vous avez déjà ces données; pas besoin de "rembobiner" et de le chercher.

lastiterline = None 
with open(filename) as f: 
    for line in f: 
     line = line.strip() 
     if line.startswith("iter"): 
      lastiterline = line 
     elif line.startswith("FLAG"): 
      if lastiterline: 
       print line 
       print lastiterline 
      lastiterline = None 

En général, il est plus simple de lire un fichier une fois et rappelez-vous les bits dont vous aurez besoin plus tard comme ils passent.

+0

Je pensais qu'il revenait à 'n' lignes et pas seulement un. –

+0

Peu importe le nombre de lignes qu'il doit parcourir. Il veut la dernière ligne 'iter', c'est-à-dire, celle qui précède les [n lignes de choses]' ('iter3' dans son premier ensemble de données et' iter5' dans la seconde). – kindall

+0

Hach. Je n'ai même pas lu votre extrait correctement. Excusez-moi. –

0

Pour de tels problèmes en général, vous pouvez lire et traiter le fichier par bloc:

def flagblocks(filename): 
    with open(filename) as f: 
     yieldlist = [] 
     for line in f: 
      if not line.strip(): 
       continue 
      if not line.startswith("FLAG"): 
       yieldlist.append(line) 
       continue 
      yield yieldlist 
      yieldlist = [] 
     yield yieldlist 


for flagblock in flagblocks("filename"): 
    process_flagblock_lines(flagblock) 

La fonction de traitement dans votre cas particulier serait encore faire essentiellement la même chose que Kindall suggéré.

La logique dans la fonction flagblocks peut ne pas être optimale ou même boguée.

Questions connexes