ну, это то же самое, что кормить его строкой, мне было интересно, есть ли способ разобрать поток

ли способ использовать регулярное выражение в потоке в Python? любить

reg = re.compile(r'\w+')
reg.match(StringIO.StringIO('aa aaa aa'))

И я не хочу делать это, получая значение всей строки. Я хочу знать, есть ли способ сопоставить регулярное выражение в srtream (на лету).

 Donal Fellows03 янв. 2012 г., 15:07
@MartinStettner: Ну, вы могли бы, если бы это был теоретико-автоматный сопоставитель без обратных ссылок (и некоторых других вещей, таких как ограничения на просмотр). Пока RE может компилироваться в один конечный автомат (NFA или DFA), он может сопоставлять вещи за один проход и, таким образом, может обрабатывать совпадения в бесконечном потоке. (Но Python использует PCRE, который не является теоретико-автоматным и которому нужны все байты там ранее.)
 SilentGhost23 янв. 2011 г., 20:22
это против идеи регулярного выражения.
 Donal Fellows04 янв. 2012 г., 14:38
@MartinStettner: Это одна из тех вещей, которые некоторые просто «знают». Сопоставители на основе стека могут поддерживать более богатый язык - это то, как вы действительно говорите, - нонужно поток токенов, который они могут сохранить внутри. (Я полагаю, что это связано с изучением этих вещей еще тогда, когда я был студентом CS).
 MartinStettner03 янв. 2012 г., 17:30
@DonalFellows я смотрел наpcre.org/pcre.txt и не обнаружили никаких признаков того, что алгоритм PCRE не основывался на теории автоматов. Конечно, для реализации обратных ссылок и запросов на просмотр необходимо поддерживать внутренний буфер, но это не помешает такому механизму, как, скажем, некоторыйneedmore обратный вызов для работы (и во многих случаях буфер не должен быть слишком большим по сравнению с размером потока бесконечности).
 MartinStettner03 янв. 2012 г., 14:30
@SlientGhost: не обязательно. Вы можете захотеть проанализировать некоторый (бесконечный) поток, используя регулярные выражения, всегда сопоставляя в текущем начале потока и возвращая совпадения в качестве итератора (и потребляя только символы, совпадающие с потоком).

Ответы на вопрос(4)

Решение Вопроса

LazyString класс, который действует как строка, но читает только столько данных из потока, сколько необходимо в настоящее время (я сделал это путем переопределения__getitem__ а также__iter__ извлекать и буферизовать символы до самой высокой доступной позиции ...).

Это не сработало (я получил "TypeError: ожидаемая строка или буфер" отre.match), поэтому я немного посмотрел на реализациюre модуль в стандартной библиотеке.

К сожалению, использование регулярных выражений в потоке кажется невозможным. Ядро модуля реализовано на языке C, и эта реализация предполагает, что весь ввод будет находиться в памяти одновременно (я полагаю, в основном из-за соображений производительности). Кажется, нет простого способа исправить это.

Я также посмотрел наPyl (Python LEX / YACC), но их использует лексерre внутренне, так что это не решит проблему.

Возможность может быть в использованииANTLR который поддерживает бэкэнд Python. Он конструирует лексер с использованием чистого кода на Python и, похоже, может работать с входными потоками. Поскольку для меня проблема не так важна (я не ожидаю, что мой вклад будет очень большим ...), я, вероятно, не буду исследовать это дальше, но это может стоить посмотреть.

 Eduardo Ivanec03 янв. 2012 г., 15:12
Хорошо исследовано, интересно. возможноacooke.org/rxpy разумная альтернатива?
 Giovanni Funchal01 апр. 2015 г., 22:08
Я просто нашел другое решение: pexpect (pexpect.readthedocs.org/en/latest/api/pexpect.html)

mmap и если вы работаете с байтовыми строками вместо Unicode, вы можете передать файл с отображенной памятью вre как будто это была быстрая строка, и она будет просто работать. Это ограничено вашим адресным пространством, а не оперативной памятью, поэтому 64-разрядная машина с 8 ГБ ОЗУ может отображать в памяти файл размером 32 ГБ.

Если вы можете сделать это, это действительно хороший вариант. Если вы не можете, вы должны обратиться к более сложным вариантам.

Стороннийregex модуль (неre) предлагает частичную поддержку совпадений, которая может быть использована для создания потоковой поддержки ... но это грязно и имеет много предостережений. Такие вещи, как lookbehinds и^ не будет работать, совпадения нулевой ширины было бы сложно получить правильно, и я не знаю, будет ли оно правильно взаимодействовать с другими расширенными функциямиregex предлагает иre не делает. Тем не менее, кажется, что это самое близкое к полному доступному решению.

Если вы пройдетеpartial=True вregex.match, regex.fullmatch, regex.search, или жеregex.finditerзатем в дополнение к отчету о полных матчах,regex также сообщит о том, что может быть совпадением, если данные были расширены:

In [10]: regex.search(r'1234', '12', partial=True)
Out[10]: <regex.Match object; span=(0, 2), match='12', partial=True>

Он сообщит о частичном совпадении, а не о полном совпадении, если больше данных может изменить результат совпадения, например,regex.search(r'[\s\S]*', anything, partial=True) всегда будет частичное совпадение.

Благодаря этому вы можете сохранить скользящее окно данных для сопоставления, расширяя его при достижении конца окна и отбрасывая использованные данные с самого начала. К сожалению, все, что может запутаться из-за исчезновения данных в начале строки, не будет работать, так что смотрите^, \b, а также\B вне Совпадения с нулевой шириной также требуют осторожного обращения. Вот подтверждение концепции, которая использует скользящее окно над файлом или подобным файлу объектом:

import regex

def findall_over_file_with_caveats(pattern, file):
    # Caveats:
    # - doesn't support ^ or backreferences, and might not play well with
    #   advanced features I'm not aware of that regex provides and re doesn't.
    # - Doesn't do the careful handling that zero-width matches would need,
    #   so consider behavior undefined in case of zero-width matches.
    # - I have not bothered to implement findall's behavior of returning groups
    #   when the pattern has groups.
    # Unlike findall, produces an iterator instead of a list.

    # bytes window for bytes pattern, unicode window for unicode pattern
    # We assume the file provides data of the same type.
    window = pattern[:0]
    chunksize = 8192
    sentinel = object()

    last_chunk = False

    while not last_chunk:
        chunk = file.read(chunksize)
        if not chunk:
            last_chunk = True
        window += chunk

        match = sentinel
        for match in regex.finditer(pattern, window, partial=not last_chunk):
            if not match.partial:
                yield match.group()

        if match is sentinel or not match.partial:
            # No partial match at the end (maybe even no matches at all).
            # Discard the window. We don't need that data.
            # The only cases I can find where we do this are if the pattern
            # uses unsupported features or if we're on the last chunk, but
            # there might be some important case I haven't thought of.
            window = window[:0]
        else:
            # Partial match at the end.
            # Discard all data not involved in the match.
            window = window[match.start():]
            if match.start() == 0:
                # Our chunks are too small. Make them bigger.
                chunksize *= 2

Да - используяgetvalue метод:

import cStringIO
import re

data = cStringIO.StringIO("some text")
regex = re.compile(r"\w+")
regex.match(data.getvalue())
 nikitautiu08 янв. 2011 г., 17:33
ну, это то же самое, что кормить его строкой, мне было интересно, есть ли способ разобрать поток

похожий вопрос, вы можете подкласс класса Matcher моего решенияstreamsearch-ру и выполнить сопоставление регулярных выражений в буфере. Проверьте kmp_example.py для шаблона. Если окажется, что классическое сопоставление Кнута-Морриса-Пратта - это все, что вам нужно, то ваша проблема будет решена прямо сейчас с помощью этой маленькой библиотеки с открытым исходным кодом :-)

Ваш ответ на вопрос