2012-09-17 3 views
10

반복되는 문자 패턴을 가질 수있는 문자열이 있습니다.문자열에서 반복되는 문자 패턴을 제거하는 정규식

'xyzzyxxyzzyxxyzzyx' 

나는 가장 작은 반복 패턴과 같은 문자열을 대체 할 정규식 작성해야합니다 :

'xyzzyxxyzzyxxyzzyx' becomes 'xyzzyx', 

'abcbaccbaabcbaccbaabcbaccba' becomes 'abcbaccba' 
+0

패턴이 알려져 있습니까? 아니면 문자열에서 반복되는 패턴을 찾으십니까? – Joel

+1

그는 내가 생각하는 가장 작은 반복 패턴을 찾고 있습니다. – arshajii

답변

5

사용하여 다음

> re.sub(r'(.+?)\1+', r'\1', 'xyzzyxxyzzyxxyzzyx') 
'xyzzyx' 
> re.sub(r'(.+?)\1+', r'\1', 'abcbaccbaabcbaccbaabcbaccba') 
'abcbaccba' 
> re.sub(r'(.+?)\1+', r'\1', 'iiiiiiiiiiiiiiiiii') 
'i' 

그것은 기본적으로 그 자체를 반복하는 패턴과 일치 (.+?)\1+을 입력하고 첫 번째 그룹 \1에 캡처 된 반복 패턴 이외의 모든 것을 제거합니다. 또한 여기서 꺼리는 한정자를 사용하면 +?과 같이 정규식을 역 추적 할 수 있습니다.

DEMO. 당신이 가장 작은 반복 패턴을 원하기 때문에

+0

이 문제는이 경우 실패합니다 : >>> re.'i' – mercador

+0

@mercador 대신에 'iiiiiiiii'대신에'+'한정 기호를 사용하지 말고 욕심이 많다. 내 대답을 업데이트했습니다. –

4

, 다음과 같은 당신을 위해 작동합니다 :

re.sub(r'^(.+?)\1+$', r'\1', input_string) 

^$ 앵커하여 문자열의 중간에 일치하지 않습니다 있는지 확인하고 대신 .+?을 사용하면 가장 짧은 패턴을 얻을 수 있습니다 ('aaaaaaaaaa'과 같은 문자열을 사용하여 결과 비교).

+1

그리고'input_string '이''a "* 1000000 +"b "'와 같으면 꽤 오랜 시간이 걸릴 수 있습니다. – hobbs

+1

역 추적하지 않고 정규식에 대한 아이디어가 있습니까? '. +? '는 무거운 역 추적을 일으킬 것입니다. – Kash

+0

'Programming Perl'과 같은 책을 읽으면 '무거운'예제로 정규 표현식을 찾을 수 있습니다. 제 생각에는 정규 표현식의 빠른 작업이 아닙니다. – gaussblurinc

2

첫 번째 그룹이 정규식 패턴을 시도하고 캡처 : 줄 바꿈

  • + 한정 기호를 제외한 모든 문자가이어야 한 선두로부터를 표시하기 위해 문자열의 시작에 대한

    ^(.+?)\1+$ 
    
    • ^ 앵커/라인
    • .
    • ?은 욕심이 많은 대신 +을 게으르게 만듭니다. 그 패턴을 나타 내기 위해 당신에게 정량와
    • () 캡처 그룹
    • \1+ 역 참조를 가장 짧은 패턴을 제공해야 문자열/라인 여기

    테스트를 종료 한 번씩

  • $ 앵커이어야 반복 : Rubular


    위의 해결 방법은 많은 bac을 수행합니다 성능에 영향을 미치는 ktracking. 이 문자열에 허용되지 않는 문자를 알고 있으면 역 추적을 제거하는 부정 된 문자 집합을 사용할 수 있습니다. 예를 들어 공백을 사용할 수없는 경우 다음과 같이 입력하십시오.

    ^([^\s]+)\1+$ 
    
  • 관련 문제