복붙노트

[PYTHON] 파이썬 정규식 파스 스트림

PYTHON

파이썬 정규식 파스 스트림

파이썬에서 스트림에 정규식 일치를 사용하는 방법이 있습니까? 처럼

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

그리고 나는 전체 문자열의 가치를 얻음으로써 이것을하고 싶지 않습니다. srtream (on-the-fly)에서 정규 표현식과 일치시키는 방법이 있는지 알고 싶습니다.

해결법

  1. ==============================

    1.나는 똑같은 문제가 있었다. 첫 번째 생각은 LazyString 클래스를 구현하는 것입니다.이 클래스는 현재와 같이 스트림에서 많은 양의 데이터를 읽는 것뿐입니다 (나는 __getitem__ 및 __iter__을 다시 구현하여 액세스하여 액세스 한 가장 높은 위치까지 문자를 가져오고 버퍼링합니다.) ).

    나는 똑같은 문제가 있었다. 첫 번째 생각은 LazyString 클래스를 구현하는 것입니다.이 클래스는 현재와 같이 스트림에서 많은 양의 데이터를 읽는 것뿐입니다 (나는 __getitem__ 및 __iter__을 다시 구현하여 액세스하여 액세스 한 가장 높은 위치까지 문자를 가져오고 버퍼링합니다.) ).

    이것은 제대로 작동하지 않았다. (re.match에서 "TypeError : expected string or buffer"를 얻었 기 때문에) 표준 라이브러리에서 re 모듈의 구현을 조금 보았다.

    불행히도 스트림에서 정규식을 사용하는 것은 불가능 해 보입니다. 모듈의 핵심은 C로 구현되어 있으며,이 구현은 전체 입력을 메모리에 한 번에 전달할 것으로 기대합니다 (주로 성능상의 이유로). 이 문제를 해결하는 쉬운 방법이없는 것 같습니다.

    PYL (Python LEX / YACC)도 살펴 보았지만, 렉서는 내부적으로 re를 사용하므로이 문제를 해결할 수 없습니다.

    파이썬 백엔드를 지원하는 ANTLR을 사용할 수도 있습니다. 순수 파이썬 코드를 사용하여 렉서를 구성하고 입력 스트림에서 작동 할 수있는 것 같습니다. 나에게 문제는 그다지 중요하지 않기 때문에 (나는 내 ​​의견이 광범위하게 커질 것이라고 기대하지 않는다.), 나는 더 이상 조사하지 않을 것이지만, 한 번 볼 가치가있을 것이다.

  2. ==============================

    2.특정 파일의 경우 mmap을 사용하여 파일을 메모리 맵핑 할 수 있고 유니 코드 대신 바이트 테스트로 작업하는 경우 메모리 맵핑 된 파일을 바이트 테스트로 전달할 수 있습니다. 그냥 일이야. 이것은 RAM이 아닌 주소 공간에 의해 제한되므로, 8GB RAM을 갖춘 64 비트 컴퓨터는 32GB 파일을 메모리 맵핑 할 수 있습니다.

    특정 파일의 경우 mmap을 사용하여 파일을 메모리 맵핑 할 수 있고 유니 코드 대신 바이트 테스트로 작업하는 경우 메모리 맵핑 된 파일을 바이트 테스트로 전달할 수 있습니다. 그냥 일이야. 이것은 RAM이 아닌 주소 공간에 의해 제한되므로, 8GB RAM을 갖춘 64 비트 컴퓨터는 32GB 파일을 메모리 맵핑 할 수 있습니다.

    이 작업을 수행 할 수 있다면 정말 좋은 옵션입니다. 할 수 없다면, 더 복잡한 옵션으로 전환해야합니다.

    타사 regex 모듈 (re가 아닌)은 스트리밍 지원을 빌드하는 데 사용할 수있는 부분 일치 지원을 제공하지만 지저분하고주의해야 할 점이 많습니다. lookbehinds와 ^와 같은 것들은 작동하지 않을 것입니다. 너비가 맞지 않으면 일치하는 것이 까다로울 것입니다. 정규 표현식이 제공하는 다른 고급 기능과 올바르게 상호 작용하는지, 다시는 그렇지 않은지 잘 모릅니다. 여전히 사용 가능한 완벽한 솔루션에 가장 가까운 것 같습니다.

    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)는 항상 부분 일치.

    이렇게하면 데이터 슬라이딩 창을 일치시킬 수 있습니다. 창이 끝나고 처음부터 소비 된 데이터를 버리면 확장 할 수 있습니다. 불행히도, 문자열의 시작 부분에서 사라지는 데이터에 의해 혼란 스러울 수있는 것은 작동하지 않으므로, lookbehinds, ^, \ 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
    
  3. ==============================

    3.이것은 오래된 문제인 것처럼 보입니다. 비슷한 질문에 게시 한 것처럼 내 솔루션 streamsearch-py의 Matcher 클래스를 서브 클래스 화하고 버퍼에서 정규식 일치를 수행 할 수 있습니다. 템플릿에 대한 kmp_example.py를 확인하십시오. 고전적인 Knuth-Morris-Pratt 매칭이 필요하다면이 작은 오픈 소스 라이브러리로 문제를 해결할 수 있습니다 :-)

    이것은 오래된 문제인 것처럼 보입니다. 비슷한 질문에 게시 한 것처럼 내 솔루션 streamsearch-py의 Matcher 클래스를 서브 클래스 화하고 버퍼에서 정규식 일치를 수행 할 수 있습니다. 템플릿에 대한 kmp_example.py를 확인하십시오. 고전적인 Knuth-Morris-Pratt 매칭이 필요하다면이 작은 오픈 소스 라이브러리로 문제를 해결할 수 있습니다 :-)

  4. ==============================

    4.예 - getvalue 메소드 사용 :

    예 - getvalue 메소드 사용 :

    import cStringIO
    import re
    
    data = cStringIO.StringIO("some text")
    regex = re.compile(r"\w+")
    regex.match(data.getvalue())
    
  5. from https://stackoverflow.com/questions/4634376/python-regex-parse-stream by cc-by-sa and MIT license