2012-01-20 4 views
6

나는 약 100 개의 클래스를 가지고 있으며, 모든 호출은 텍스트 프로토콜의 다른 유형의 데이터를 처리하지만, 많은 파일을 가지고 있고 분석을 기반으로한다. regex은 내 코드 실행의 88 %를 차지했다.Regex에 대한 빠른 대체

{ 
    Match m_said = Regex.Match(line, @"(.*) said,", RegexOptions.IgnoreCase); 
    if (m_said.Success) 
    { 
    string playername = ma.Groups[1].Value; 
    // some action 
    return true; 
    } 
} 

{ 
    Match ma = Regex.Match(line, @"(.*) is connected", RegexOptions.IgnoreCase); 
    if (ma.Success) 
    { 
    string playername = ma.Groups[1].Value; 
    // some action 
    return true; 
    } 
} 
{ 
    Match ma = Regex.Match(line, @"(.*): brings in for (.*)", RegexOptions.IgnoreCase); 
    if (ma.Success) 
    { 
    string playername = ma.Groups[1].Value; 
    long amount = Detect_Value(ma.Groups[2].Value, line); 
    // some action 
    return true; 
    } 
} 

는 다른 빠른 솔루션 Regex을 대체 할 수있는 방법은 다음과 같습니다 코드의 이러한 유형의

많은? 루프 테스트 regexps '에 대한

+1

내가 사용하는 정규식의 종류에 따라 다르다고 생각합니다 ... 샘플을 제공하십시오! –

답변

8

, 그것은 루프의 외부 사전 컴파일을 종종 빠른 루프의 내부 단지 테스트는을.

먼저 각기 다른 패턴으로 다른 정규식을 선언하고 두 번째 단계에서 테스트 할 텍스트로 Match()만을 호출해야합니다.

+1

RegEx 클래스에 캐시가 없습니까? –

+0

@HenkHolterman : 참으로. 방금 그걸 확인 했어. (나는 캐시 메커니즘을 제공하지 않는 PCRE에 더 익숙하다.) 캐시는 OP에 의해 만들어진 정적'Regex.Match()'호출에 대해 작동해야한다. 아니면 너무 많은 정규 표현식이 관련되어 있고'Regex.CacheSize'는 퍼포먼스 향상을 위해 탐구해야 할 길입니다 (그러나 나는 의심 스럽습니다)? – Seki

+0

감사 인사는 10 배 빠르게 작동합니다 ;-))))) – Svisstack

1

당신은 정규식 사전에 정규식을 컴파일 시도하거나 하나 (괴물)로 모든 개별 정규식 표현을 결합 고려할 수 :

Match m_said = Regex.Match(line, 
      @"(.*) (said|(is connected)|...|...),", 
      RegexOptions.IgnoreCase); 

당신은 다음 경기의 종류가 발생한 결정하기 위해 두 번째 캡처 그룹을 테스트 할 수 있습니다. 내가 정규식 여기에 많은 일을 할 수 있지만, 알고

+0

이것은 파일을 한 번만 검색하려고 시도하는 유일한 대답입니다. –

+0

가능한 텍스트에 따라 @ "(. *) said"버전에 문제가있을 수 있습니다 : User17이 "나는 이미 말했어!"라고한다면? - 정규식은 틀린 것을 발견 할 것입니다. " –

+1

그 일을 할 수 없다. 예를 들어 X 명령 Y가 아닌 다양한 형식의 줄이있다. – Svisstack

1

는 수, 당신의 정규식을 미리 컴파일에서

+1

나는이 사이트가 내 눈알을 강간했다고 생각한다. – adelphus

+0

맞아요. -_- –

3

을 제외하고 벤치 마크 섹션의 사항 String.split

http://www.dotnetperls.com/split 대 char.Split 대 정규식과 벤치 마크 보다 정확한 정규 표현식을 작성함으로써 성능 이점을 얻을 수 있습니다.

(.*) is connected 의미 : 먼저 전체 문자열을 (즉, .* 부분)가 is connected 일치 할 수 때까지, 다음 한 번에 하나 개의 문자를 역 추적 일치 이러한 측면에서, .* 거의 항상 나쁜 선택이 될 것입니다.

문자열이 매우 짧거나 is connected이 문자열 끝에 매우 가까운 경우가 아니라면 많은 시간이 소요되는 역 추적이 필요합니다.

허용되는 일치 항목을 구체화 할 수 있다면 성능을 향상시킬 수 있습니다.

예를 들어 영숫자 문자 만 허용되는 경우 (\w+) is connected이 좋습니다. 공백 문자가 아닌 문자이면 (\S+) is connected을 사용하십시오. 등, 유효한 일치에 대한 규칙에 따라.

구체적인 예를 들어, 캡처 된 일치 항목을 수행하는 것처럼 보이지 않으므로 정규식을 모두 삭제하고 고정 된 부분 문자열 만 찾을 수도 있습니다. 결국 가장 빠른 방법은 실제 입력과 요구 사항에 달려 있습니다.

+0

가! 나는 정규식의 위대한 강점 중 하나에 대해 DFAs에 컴파일 될 수 있다는 의견을 남기려고하고 있었고 백 트랙킹이 필요하지 않았습니다. 하지만 regexps의 .NET 구현에 대한 문서를 살펴 보았습니다. [* 당신 말이 맞아요! *] (http://msdn.microsoft.com/en-us/library/dsy130b4.aspx) –

2

표현식을 다시 사용할 수 있는지, 메소드가 여러 번 호출되는지는 모르겠지만 그렇다고하더라도 정규 표현식을 사전 컴파일해야합니다. 샘플에서

private static readonly Regex xmlRegex = new Regex("YOUR EXPRESSION", RegexOptions.Compiled); 

,이 방법은이 표현을 '컴파일'를 사용할 때마다,하지만 표현이 const를 그대로이 unneccesary입니다 :이보십시오.이제는 컴파일 된이 컴파일 된 것입니다. 단점은 표현식에 처음 액세스 할 때 약간 느리다는 것입니다.

+1

감사합니다 ;-) 이 정적 필드에 대한 좋은 대답입니다. – Svisstack