Pregunta

Supongamos que abre un archivo y realiza una búsqueda () en algún lugar del archivo, ¿cómo sabe la línea de archivo actual?

(Personalmente lo resolví con una clase de archivo ad-hoc que asigna la posición de búsqueda a la línea después de escanear el archivo, pero quería ver otras sugerencias y agregar esta pregunta a stackoverflow, ya que no pude encontrar la problema en cualquier lugar en google)

¿Fue útil?

Solución

Aquí es cómo abordaría el problema, utilizando la mayor pereza posible:

from random import randint
from itertools import takewhile, islice

file = "/etc/passwd"
f = open(file, "r")

f.seek(randint(10,250))
pos = f.tell()

print "pos=%d" % pos

def countbytes(iterable):
    bytes = 0
    for item in iterable:
        bytes += len(item)
        yield bytes

print 1+len(list(takewhile(lambda x: x <= pos, countbytes(open(file, "r")))))

Para un enfoque un poco menos legible pero mucho más perezoso, use enumerar y dropwhile :

from random import randint
from itertools import islice, dropwhile

file = "/etc/passwd"
f = open(file, "r")

f.seek(randint(10,250))
pos = f.tell()

print "pos=%d" % pos

def countbytes(iterable):
    bytes = 0
    for item in iterable:
        bytes += len(item)
        yield bytes

print list(
        islice(
            dropwhile(lambda x: x[1] <= pos, enumerate(countbytes(open(file, "r"))))
            , 1))[0][0]+1

Otros consejos

Cuando usas seek (), python usa los desplazamientos de puntero para saltar a la posición deseada en el archivo. Pero para conocer el número de línea actual, debe examinar cada carácter hasta esa posición. Por lo tanto, también puede abandonar search () a favor de read ():

Reemplazar

f = open(filename, "r")
f.seek(55)

con

f = open(filename, "r")
line=f.read(55).count('\n')+1
print(line)

Tal vez no desee utilizar f.read (num) ya que esto puede requerir mucha memoria si num es muy grande. En ese caso, podrías usar un generador como este:

import itertools
import operator
line_number=reduce(operator.add,( f.read(1)=='\n' for _ in itertools.repeat(None,num)))
pos=f.tell()

Esto es equivalente a f.seek (num) con el beneficio adicional de proporcionarte line_number .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top