2012-09-26 5 views
4

파일에서 'path :'토큰을 찾아 내려고 다음 숫자 (임의의 숫자)를 숫자로 읽으려고합니다 (': path, 123 '파일을 찾은 다음 정수 123을 읽습니다.) 그런 다음 현재 탐색 위치와 pos + 123 사이의 문자를 읽습니다 (목록에 저장하거나 무엇이든). 그런 다음 ': 경로'와 일치 할 때까지 탐색하고 프로세스를 반복하십시오.파이썬을 사용하여 큰 파일에서 regex를 찾으십시오.

나는 기능을 원하는

조금 같은 :

 
def fregseek(FILE, current_seek, /regex/): 

. 
. 
    value_found = ? # result of reading next N chars after :path,[0-9]+ 
. 
. 
    return next_start_seek, value_found 

가에 대한 일치의 모든 숫자가 될 수 있습니다 라인에서 '경로', 그 문자열이 다음에 지정된 문자의 수 내에서 발생할 수 있습니다 ' , '. 각 줄에서 읽는 지저분한 쓰레기를 작성한 다음, 일치로 표시된 첫 번째 N 개의 문자의 각 줄 촘촘한 부분에 대해 쓰고 그 문자열이 모두 먹힐 때까지 계속 처리합니다. 그런 다음 다음 문자열을 읽습니다.

이것은 정말 끔찍한 일로, 정말로해야 할 일이있을 때 잠재적으로 거대한 파일의 모든 줄을 버리고 싶지 않습니다. (특히 줄 바꿈은 관련이 없으므로 추가 처리 단계가 필요합니다. 라인은 파일에서 끌어 오기가 쉽지 않다.).

그래서,저기서 저의 문제는 해결하고 싶습니다. 나는 경기를 찾고, 가치를 읽고, 다음 경기를 기다리고있는 그 가치의 끝에서부터 계속하고 파일이 고갈 될 때까지 계속해야합니다.

사람이 나를 도울 수 있다면 나는 :) 그들로부터 듣고 행복 할 것이다

나는 가능하면 표준이 아닌 라이브러리를 피하기 위해 싶습니다

, 나는이 최소한의 것입니다 또한 짧은 코드처럼하지만 것 내 관심사 (속도와 메모리 소비가 중요한 요인이지만, 나는 단지 그것이 무엇인지 알았다면 그 안에 작은 기능이있는 라이브러리를 부트 스트랩하기 위해 50 loc를 추가하기를 원하지 않는다.)

필자는이 점에서 파이썬이 파이썬보다 뛰어나다면 perl을 대신 사용할 것이며, 끔찍하게 느리지 만 않으면 영리한 sed/awk/bash 스크립트 등도 열어 둡니다.

대단히 감사드립니다.

+0

정규식을 사용해야합니까? ": path"와 같은 토큰을 찾으려는 경우 불필요하며 문자열 검색 만하면 더 쉽고 효율적입니다. – abarnert

+0

또한 검색에 대해 계속 이야기하지만 모든 바이트를 검색하지 않고 검색을 수행 할 방법이 없으며 한 번에 할 수없는 것을 볼 수 없으므로 왜 필요한지 확실하지 않습니다. 전혀 추구. – abarnert

+0

의견 주셔서 감사합니다. 한 번에 전체 파일을 읽을 필요가 없다면 문자열 검색이 좋습니다. 그러나 내가 읽은 모든 덩어리를 효율적으로 처리해야합니다. 모든 것을 읽는 것보다 더 좋은 방법이 있는지 확실하지 않습니다. , 비록 내가 임의로 큰 파일을 처리 할 수 ​​싶습니다. 이상적으로 벤치마킹 할 수있는 몇 가지 옵션이 있지만 지금은 내 진절머리 난 코드가 있습니다. 이미 현재 가지고있는 것보다 훨씬 나은 답변이 이미 있습니다. – sillyMunky

답변

3

, 당신은 바로 찾아 슬라이스로이 작업을 수행 할 수 있습니다.

어느 것이 든 간단한 해결책은 전체 파일을 메모리로 읽어 들이고 그 결과로 str/bytes 개체를 찾아서 조각내는 것입니다.

그러나 전체 파일을 메모리로 읽을 수 없거나 작동하지 않을 경우에는 작동하지 않습니다.

파일이 < < 2GB이거나 64 비트 파이썬으로 작업해야하며 합리적인 플랫폼 (POSIX, 현대식 Windows 등)을 사용하고 있다면 다행히도 대신 mmap 파일을 메모리에 저장할 수 있습니다. mmap 객체에는 문자열과 동일한 메소드의 하위 집합이 있으므로 전체 파일을 메모리로 읽는 것처럼 문자열이있는 것처럼 가장 할 수는 있지만 파이썬 구현과 OS를 사용하여 계산할 수 있습니다 합리적인 효율성으로 작업하십시오.

귀하의 Python 버전에 따라 re은 문자열 인 것처럼 mmap을 스캔하지 못할 수도 있습니다. 그러나 작동이 느리거나 느리거나 잘 작동 될 수 있습니다.

def findpaths(fname): 
    with open(fname, 'rb') as f: 
    m = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) 
    for match in re.finditer(':path,([0-9]+)', m): 
     yield m[match.end():match.end()+int(match.group(1))] 

가 (이 그냥 사용 BrtH의 대답과 동일합니다 : 예외를 던지거나 당신이이 완료 예상보다 훨씬 느린하지 않는 경우에 따라서, 당신은뿐만 아니라 먼저 시도하고 있습니다 문자열 대신 mmap을 사용하고 목록 대신 생성기로 재구성합니다. 물론 대괄호를 대괄호로 바꾸어 후자를 처리 할 수도 있습니다.)

이전 버전을 사용하는 경우 (효율적으로) mmap 수 없습니다 파이썬의 버전, 조금 더 복잡 :

이것은 아마도 nextdigits 함수를 작성하는 가장 빠른 방법은 아닙니다. 나는 그것이 실제로 중요 할 것이라는 것을 확신하지 못하지만, 만약 그렇다면, 다른 가능성은 m[n+6:n+A_BIG_ENOUGH_NUMBER]을 잘라내어 정규식으로 만들거나 커스텀 루프를 작성하거나, 아니면 ... 병목이 있다면, 당신은 내가까지 일을 분할, 내 시험

... JIT (PyPy, 자이 썬, 또는 IronPython의)와 통역사로 전환하여 훨씬 더 많은 혜택을받을 수 있습니다 findpaths 문자열과 같은 오브젝트를하고, 호출자는 with open을한다 그리고 mmap 비트이고 findpathsm을 전달합니다. 나는 간결함을 위해서 여기에서 그것을하지 않았다.

어쨌든, 나는 다음과 같은 데이터에 대해 두 버전 테스트 한 :

BLAH:path,3abcBLAH:path,10abcdefghijklmnBLAH:path,3abc:path,0:path,3abc 

을 출력했다 :

abc 
abcdefghij 
abc 

abc 

내가 그 올바른 생각?

이전 버전으로 인해 CPU가 100 % 회전하는 경우 루프 내에서 i이 올바르게 증가하지 않았을 것입니다. 그것은 가장 일반적인 이유는 당신이 긴밀한 구문 분석 루프에서 그 행동을 얻을. 어쨌든 현재 버전으로 재현 할 수 있다면 데이터를 게시하십시오.

+0

제안 해 주셔서 감사합니다. 발전기를 반납하는 아이디어를 좋아합니다. 그게 꽤 나를 위해 일하는 이유는, 실제로 반환 된 발전기를 사용하려고 할 때 어떤 일이 일어나지도 않고 모든 시스템 리소스를 우회하여 죽이기 (매우 작은 테스트 파일로)가 필요하기 때문입니다. 어떻게 사용했는지 보여 주시겠습니까? – sillyMunky

+0

이것은 좋은 대답이며 아마 내 것보다 나은 요구 사항을 충족하므로 +1합니다. – BrtH

+1

하지만 이해할 수없는 것이 하나 있습니다. 당신은 카운트가 이미 알려져 있고 일정하다고 가정하는 것 같습니다. 그러나 질문을 올바르게 이해했다면, 그렇지 않습니다. 또한 카운트를 찾아야합니다. 그리고 카운트가 항상 세 자리 숫자가 아니면, 당신은 정규식으로 그것을 찾아야 할 것이다. 그리고''path : {적어도 하나의 자리} '라는 단어가 겹칠 수 없기 때문에'i = n + 7'을 사용할 수 있다고 생각합니다. – BrtH

2

당신은 파이썬에서 거의 한 라인에서 작업을 수행 할 수 있습니다

with open('filename.txt') as f: 
    text = f.read() 

results = [text[i[0]:i[0] + i[1]] for i in 
      ((m.end(), int(m.group(1))) for m in 
      re.finditer(':path,([0-9]+)', text))] 

주 : 검증되지 않은 ... 당신이 정규 표현식에 필요하지 않은 경우

+0

그게 작은 파일을 위해 나를 위해 잘 작동합니다, 대단히 감사합니다! 그것이 좋은 대답이고 훨씬 더 효율적이기 때문에 나는 upvoted했다. 한 번에 전체 파일을 읽을 필요가 없지만 임의로 큰 파일을 처리하는 대답을 기다리고 있습니다 (아마도 mmap을 사용하고 있을까요?). 여기에서 찾지 못한다면, 필자의 요구 사항의 정점을 충족시키지 못하더라도 훨씬 더 광범위한 파일로 이동할 수 있으므로 도움이 될 것입니다. 주문!). 기여에 다시 한번 감사드립니다. – sillyMunky

관련 문제