Подтвердить что ты не робот

Как я re.search или re.match для целого файла, не читая все это в памяти?

Я хочу, чтобы иметь возможность запускать регулярное выражение для всего файла, но я хотел бы иметь возможность не читать весь файл в памяти сразу, поскольку я могу работать с довольно большими файлами в будущем, Есть ли способ сделать это? Спасибо!

Разъяснение: Я не могу читать строки за строкой, потому что он может охватывать несколько строк.

4b9b3361

Ответ 1

Вы можете использовать mmap для сопоставления файла с памятью. Затем содержимое файла можно получить как обычную строку:

import re, mmap

with open('/var/log/error.log', 'r+') as f:
  data = mmap.mmap(f.fileno(), 0)
  mo = re.search('error: (.*)', data)
  if mo:
    print "found error", mo.group(1)

Это также работает для больших файлов, содержимое файла внутренне загружается с диска по мере необходимости.

Ответ 2

Это зависит от файла и регулярного выражения. Лучшее, что вы могли бы сделать, это прочитать файл в строке за строкой, но если это не сработает для вашей ситуации, вы можете застрять в том, чтобы вытащить весь файл в память.

Давайте скажем, например, что это ваш файл:

Lorem ipsum dolor sit amet, consectetur
adipiscing elit. Ut fringilla pede blandit
eros sagittis viverra. Curabitur facilisis
urna ABC elementum lacus molestie aliquet.
Vestibulum lobortis semper risus. Etiam
sollicitudin. Vivamus posuere mauris eu
nulla. Nunc nisi. Curabitur fringilla fringilla
elit. Nullam feugiat, metus et suscipit
fermentum, mauris ipsum blandit purus,
non vehicula purus felis sit amet tortor.
Vestibulum odio. Mauris dapibus ultricies
metus. Cras XYZ eu lectus. Cras elit turpis,
ultrices nec, commodo eu, sodales non, erat.
Quisque accumsan, nunc nec porttitor vulputate,
erat dolor suscipit quam, a tristique justo
turpis at erat.

И это было ваше регулярное выражение:

consectetur(?=\sadipiscing)

Теперь это регулярное выражение использует положительный результат и будет соответствовать строке "consectetur", если сразу же следует какой-либо символ пробела, а затем строка "adipiscing".

Итак, в этом примере вам нужно будет прочитать весь файл в памяти, потому что ваше регулярное выражение зависит от всего файла, который обрабатывается как одна строка. Это один из многих примеров, которые потребовали бы, чтобы ваша целая строка в памяти работала для определенного регулярного выражения.

Я предполагаю, что неудачный ответ заключается в том, что все зависит от вашей ситуации.

Ответ 3

Если это большое дело и стоит каких-то усилий, вы можете преобразовать регулярное выражение в конечный конечный автомат, который читает файл. FSM может иметь сложность O (n), что означает, что она будет намного быстрее, так как размер файла становится большим.

Вы сможете эффективно сопоставлять шаблоны, которые охватывают строки в слишком больших файлах для размещения в памяти.

Вот два места, которые описывают алгоритм преобразования регулярного выражения в FSM:

Ответ 4

Это один из способов:

import re

REGEX = '\d+'

with open('/tmp/workfile', 'r') as f:
      for line in f:
          print re.match(REGEX,line)
  • с оператором в python 2.5 происходит автоматическое закрытие файла. Следовательно, вам не нужно беспокоиться об этом.
  • Итератор над файловым объектом является эффективным с точки зрения памяти. то есть он не будет читать больше, чем линейку памяти в данный момент времени.
  • Но обратная сторона этого подхода заключается в том, что для огромных файлов потребуется много времени.

Другим подходом, который приходит мне на ум, является использование метода read (size) и file.seek(offset), который будет считывать часть размера файла за раз.

import re

REGEX = '\d+'

with open('/tmp/workfile', 'r') as f:
      filesize = f.size()
      part = filesize / 10 # a suitable size that you can determine ahead or in the prog.
      position = 0 
      while position <= filesize: 
          content = f.read(part)
          print re.match(REGEX,content)
          position = position + part
          f.seek(position)

Вы также можете объединить эти два, чтобы создать генератор, который в то время возвращал бы содержимое определенных байтов и перебирал содержимое, чтобы проверить ваше регулярное выражение. Эта ИМО будет хорошим подходом.

Ответ 5

Для шаблонов с одной строкой вы можете выполнять итерацию по строкам файла, но для многострочных шаблонов вам нужно будет прочитать все (или часть, но это будет сложно отслеживать) файла в памяти.

Ответ 6

Откройте файл и выполните итерацию по строкам.

fd = open('myfile')
for line in fd:
    if re.match(...,line)
        print line

Ответ 7

f = open(filename,'r')
  for eachline in f:
    string=re.search("(<tr align=\"right\"><td>)([0-9]*)(</td><td>)([a-zA-Z]*)(</td><td>)([a-zA-Z]*)(</td>)",eachline)
    if string:
      for i in range (2,8,2):
        add = string.group(i)
        l.append(add)