Есть два трюка: первый - это регулярное выражение re.finditer (и метод).
Вторым является использование модуля mmap .
Из документации по re.DOTALL мы можем заметить, что .
не соответствует символам новой строки:
без этого флага '.' будет соответствовать чему-либо, кроме новой строки.
Таким образом, если вы ищете все совпадения в любом месте файла (например, при чтении в строку, используя f.read()
), вы можете притвориться, что каждая строка представляет собой изолированную подстроку (однако, это не совсем так. Если вы хотите утверждения ^ и $, чтобы работать таким образом, используйте re.MULTILINE). Теперь, поскольку вы заметили, что мы предполагаем, что в каждой строке имеется только ноль или одно вхождение, нам не нужно беспокоиться о том, чтобы re.finditer () соответствовал больше, чем следовало бы (потому что это будет!). Так что сразу вы можете заменить все это на итерацию по finditer ():
fileList = open(inFile, 'r')
pattern = re.compile(r'foo(.*)bar')
for result in pattern.finditer(fileList.read()):
print result.groups(1)
Это не действительно хорошо, хотя. Проблема здесь в том, что весь файл читается в память для вашего удобства. Было бы неплохо, если бы был удобный способ сделать это, не разбивая большие файлы. И, ну, есть! Войдите в модуль mmap.
mmap позволяет вам обрабатывать файл, как если бы он был строкой (изменяемая строка, не меньше!), И он не загружает все это в память. Короче говоря, вместо этого вы можете использовать следующий код:
fileList = open(inFile, 'r+b')
fileS = mmap.mmap(fileList.fileno(), 0)
pattern = re.compile(r'foo(.*)bar')
for result in pattern.finditer(fileS):
print result.groups(1)
и он будет работать точно так же, но без использования всего файла сразу (надеюсь).