2013-09-24 6 views
2

내 프로그램에 작은 문제가 있습니다. 대부분의 경우 while 루프로 인해 멈추는 경향이 있습니다.패턴 일치 중 멈춤

내가하려는 것은 Java 주석을 찾아서 대체하는 것입니다. 따라서 블록 주석을 입력 할 때 /*과 함께 해당 주석을 엽니 다. 닫는 끝 부분 (*/)이 없으면 프로그램은 고정되어 있고 사용할 수없는 곳에서 5-6 초가 걸립니다. 나는 더 많은 정규 표현식과 성능상의 문제가없는 10,000 줄 이상의 파일을 가지고 실행했기 때문에 모든 유형의 성능 저하는 놀랄만큼 혼란 스러울 뿐더러 5 초의 지연이 있습니다. 나는이 문제를 추측하고

private static final String COMMENT_MATCHER = "(//.*)|(/\\u002A((\\s)|(.))*?\\u002A/)"; 

private String clearMatches(String code, final String regex) { 
    final Pattern pattern = Pattern.compile(regex); 
    final Matcher matcher = pattern.matcher(code); 
    while (matcher.find()) { 
     final String match = matcher.group(); 
     code = code.replace(match, CharBuffer.allocate(match.length()).toString()); 
    } 
    return code; 
} 

는 많은 경기를 찾는 인해 길 잃은 별표 (*)로, 그들 모두를 반복 내에 자리 잡고 있습니다.

감사합니다.

+0

나는 당신이 두 개의 샷 방법을 수행하여 디버깅을 도울 수 있으리라 생각합니다. 예를 들어, 두 개의 상수'SINGLE_LINE_COMMENT_MATCHER'와'MULTI_LINE_COMMENT_MATCHER'를 가지고 있습니다. 각각의 정규 표현식을 가지고 있습니다. – Meesh

+0

@Meesh 정규 일치가 주석 일치와 일치 할 때, 다중 회선 주석이 끝나지 않은 경우입니다. 어느 쪽을 타이핑 할 때 당신은 우연히 만난다. – Obicere

+1

당신의 패턴은''Pattern.DOTALL''로 컴파일하면 좀 더 읽기 쉽도록 줄여 줄 수 있습니다. (적어도 나를 위해서) 버전''[[^ \ n] * | /[**.*?[*]/ " 시작시'(? s)'플래그를 추가 하시겠습니까? – Pshemo

답변

2

타이밍 관찰은 놀라운 일이 아닙니다. Java 정규 표현식 매칭은 역 추적으로 인해 매우 느릴 수 있습니다 (즉, n이 정규 표현식의 길이 인 경우 O (2 ** n)). 때로는 역 추적을 피하기 위해 정규 표현식을 수정할 수 있으므로 빠른 속도가 될 것입니다.

하나의 빠른 아이디어는 소유 지정자를 사용하고 있습니다 (http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html 참조). 또 다른 빠른 속도 아이디어는 더 적은 수의 | 연산자를 사용하는 것입니다.

이 시도 :

private static final String COMMENT_MATCHER = "(//.*+)|(?s)(/[*].*?[*]/)"; 
+0

와우, 효과가있었습니다! 나는 정규 표현식으로는 최고가 아니며, 나는 그것에 대해 알지 못했다. 고마워. – Obicere

4

이 시도 :

COMMENT_MATCHER = "//[^\r\n]*+|/[*](?:(?![*]/)[\\s\\S])*+[*]/"; 

상당히 빨리 실행해야한다.

패턴의 빠른 휴식 다운 - 멀티 라인 주석에 대한 하나의 단일 줄 주석에 대해 하나의

 

//     # match "//" 
[^\r\n]*+   # possessively match any chars other than line break chars 
|     # OR 
/[*]    # match "/*" 
(?:     # start non-capture group 
    (?![*]/)[\\s\\S] # match any char, only if "*/" is not ahead 
)*+     # end non-capture group and possessively repeat zero or more times 
[*]/    # match "*/"