수색…


Backtracking의 원인은 무엇입니까?

일치 항목을 찾으려면 정규식 엔진이 문자를 하나씩 사용합니다. 부분 일치가 시작되면 엔진은 시작 위치를 기억하므로 다음 문자가 일치하지 않을 경우 다시 돌아갈 수 있습니다.

  • 경기가 완료되면 역 추적이 없습니다.
  • 일치가 완료되지 않은 경우 엔진은 전체 일치 항목을 찾기 위해 문자열을 역 추적합니다 (예전 테이프를 되감습니다).

예를 들어 : abc123def 문자열에 대한 \d{3}[az]{2} 는 다음과 같이 탐색됩니다.

abc123def
^ Does not match \d
abc123def
 ^ Does not match \d
abc123def
  ^ Does not match \d
abc123def
   ^ Does match \d (first one)
abc123def
    ^ Does match \d (second one)
abc123def
     ^ Does match \d (third one)
abc123def
      ^ Does match [a-z] (first one)
abc123def
       ^ Does match [a-z] (second one)
           MATCH FOUND

이제 regex를 같은 문자열 ( abc123def )에 대해 \d{2}[az]{2} abc123def .

abc123def
^ Does not match \d
abc123def
 ^ Does not match \d
abc123def
  ^ Does not match \d
abc123def
   ^ Does match \d (first one)
abc123def
    ^ Does match \d (second one)
abc123def
     ^ Does not match [a-z]
abc123def
    ^ BACKTRACK to catch \d{2} => (23)
abc123def
      ^ Does match [a-z] (first one)
abc123def
       ^ Does match [a-z] (second one)
           MATCH FOUND

역 추적은 왜 함정이 될 수 있습니까?

regex 엔진은 모든 경로를 탐색하려고하기 때문에 선택적 양수 또는 대체 구조로 인해 역 추적이 발생할 수 있습니다. aaaaaaaaaaaaaa 에 대해 정규식 a+b 를 실행하면 일치하는 항목이 없으므로 엔진에서 매우 빨리 찾을 수 있습니다.

하지만 (aa*)+b 정규 표현식을 변경하면 조합 수는 매우 빠르게 증가하고 대부분의 (최적화되지 않은) 엔진은 모든 경로를 탐색하려고 시도 할 것이며 영원을 찾아 일치를 찾거나 제한 시간 초과. 이를 치명적인 역 추적 이라고합니다.

물론 (aa*)+b 는 초보자 오류 인 것처럼 보일 수 있지만 여기에 요점을 설명하기 위해 나와 있습니다. 때로는 똑같은 문제가 있지만 더 복잡한 패턴으로 끝나기도합니다.

catgerophic backtracking의 더 극단적 인 경우는 정규식 (x+x+)+y (아마 여기 또는 여기 에서 본 것)에서 발생합니다. x 및 그 밖의 다른 것을 포함하는 문자열을 찾아내는 기하 급수적 인 시간이 필요합니다. xxxxxxxxxxxxxxxxxxxx )이 일치하지 않습니다.

어떻게 피하는가?

되도록 구체적으로 가능한 한 경로를 줄이십시오. 일부 정규식 matchers는 Thkpson NFA를 기반으로하기 때문에 awk 또는 grep 포함 된 것과 같은 역 추적에 취약하지 않습니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow