2012-03-12 5 views
4

나는 어떻게해야하는지 아직 알지 못하는 특별한 사용 사례가 있습니다. field_name/field_length를 기준으로 문자열을 분석하고 싶습니다. 이를 위해 다음과 같은 정규 표현식을 정의합니다.명명 된 그룹 및 대체를 사용하여 파이썬 정규식으로 문자열 해설

'(?P<%s>.{%d})' % (field_name, field_length) 

그리고 모든 필드에 대해이 작업을 반복합니다.

는 또한 각 필드의 오른쪽에있는 공백을 제거하는 정규식이 :

self.re_remove_spaces = re.compile(' *$') 

이 같은 각 필드 얻을 수있는이 방법 : 나는이 처리를 수행 할 필요가

def dissect(self, str): 
    data = { } 
    m = self.compiled.search(str) 
    for field_name in self.fields: 
     value = m.group_name(field_name) 
     value = re.sub(self.re_remove_spaces, '', value) 
     data[field_name] = value 
    return data 

을 수백만 개의 문자열이 있으므로 효율적이어야합니다.

나를 괴롭히는 이유는 compiled.search 대신 compiled.sub을 사용하여 절개 + 공간 제거를 한 번 수행하는 것이 좋지만이 방법은 잘 모릅니다.

특히, 내 질문은 :

어떻게 파이썬 정규 표현식에에 명명 된 그룹과 결합 정규식 대체를 수행합니까?

+0

''(? <%s>. % d) '% ...'는 (' .12)''와 (과) 비슷한 표현이 유효한 파이썬 정규 표현식이 아닙니다. – interjay

+0

죄송합니다. P와 {}이 (가) 빠졌습니다.나는 여전히 이것을 테스트하고 있으므로 더 많은 버그가있을 수 있습니다. – dangonfast

답변

4

내가 각 필드는 테이블처럼 문자열에서 서로 옆에 앉아 그것을 가지고, 예를 들면 :

당신이 그 사건을해야 할 경우 그룹의 끝에 |을 추가 할 수 있습니다 작동합니다
name  description  license 
python language   opensource 
windows operating system proprietry 

그래서 각 필드의 길이를 미리 알고 있다고 가정하면 정규식을 사용하지 않고 훨씬 간단하게 할 수 있습니다.

>>> self.dissect('python language   opensource') 
{'lang': 'python', 'license': 'opensource', 'desc': 'language'} 

이 당신이 생각 할 노력하고 무엇인가 fields = [('lang', 9), ('desc', 19), ('license', 12)] 경우,

def dissect(text): 
    data = {} 
    for name, length in fields: 
     data[name] = text[:length].rstrip() 
     text = text[length:] 
    return data 

(가 내장 str 유형과 충돌한다 이후 BTW, str 변수에 대한 좋은 이름이 아닙니다)?

+0

예, 이것이 제가 시도한 것입니다. 그리고 실제로 첫 번째 구현은 문자열 조각을 사용하여 수행되었습니다. 어떻게 든이 정규식은이 시나리오에서 더 잘 수행 될 것이므로 구현을 명명 된 그룹과 정규 표현식으로 바 꾸었습니다. 내 프로세스 기능이 이제 몇 시간 동안 실행되고 슬라이스가 더 빠르다는 느낌이 들었다. 아마도 필자는 그것을 다시 변경하거나 성능 테스트를 수행하기 위해 두 가지 구현을 모두 유지할 것입니다. – dangonfast

+0

슬라이스가 훨씬 빠르다는 것을 알게 될 것입니다. 그러나 오랫동안 계속 실행 중이면 확실하게 프로파일 링하고 병목 현상이 어디에 있는지, 그리고 속도를 더욱 빠르게하는 방법을 확인해야합니다. – aquavitae

+0

처리 할 레코드가 많으므로 오랜 시간이 걸립니다. – dangonfast

0

sub을 사용하면 직접 원하는 부분과 일치시킬 수 있습니다.

당신은 같은 것을 사용할 수 있습니다

(?P<name>.{0,N}(?<!)) 

을하지만 경기가 정확히 N 오래해야하는 경우처럼 내다을 사용할 수 있습니다이 사용하는 것보다 더 나은 성능 인 경우

(?=(?P<name>.{0,N}(?<!))).{N} 

추가적인 트림은 의심 스럽다. 당신은 그것을 시도하고 우리에게 알려줄 수 있습니다.

일치 항목이 공백 일 때만이 표현식은 공백이기도 전에 문자도 나타납니다.

(?P<name>.{0,N}(?<!)|) 
+0

예, 필드는 모두 공백 일 수 있으며 앞 필드는 공백이 될 수도 있습니다. 그리고 들판은 정확한 길이를 가지고 있습니다. – dangonfast

+0

@ gonvaled이면 마지막 제안과 함께 두 번째 표현식을 사용할 수 있습니다. '(? = . {0, N} (? Qtax

+0

입력을 수정할 수 없습니다. 데이터. '| '를 추가하는 것은 불가능합니다. – dangonfast