2010-01-17 2 views
9

문자열이 특정 값으로 끝나는 지 확인하려면 Regex (.NET 구문)을 작성해야합니다. 특히 파일에 특정 확장명 (또는 확장명 집합)이 있는지 테스트해야합니다.Regex를 사용하여 "EndsWith"를 효율적으로 테스트하십시오.

내가 사용하고 해결하기 위해 노력하고있어 코드 : 인 (

역 추적에 아마도 때문에 내 시나리오에서 실패 일치 (대한 무시 무시 느린
.*\.(png|jpg|gif)$ 

는 단순히 .*을 제거. API가 일치 테스트 만하고 아무 것도 추출하지 않기 때문에) 정규식을 훨씬 효율적으로 만듭니다.

여전히 꽤 비효율적 인 것처럼 느껴집니다. 여기에서 확실하지 않은 것이 있습니까?

불행히도, 문제의 API를 제어하지 않기 때문에 정규 표현식을 작업에 적합한 도구로 간주하지 않더라도 정규 표현식을 사용해야합니다.

나는 또한 RegexOptions.RightToLeft를 사용하여 몇 가지 테스트를했고, 나는 ^.*\.(png|jpg|gif)$ 내 테스트 케이스에서 좀 더 성능을 짜낼 수 있지만 내가 정규식 자체의 문자열 내에서 RightToLeft 옵션을 지정하는 방법을 찾을 수 있다는 것을 발견 그래서 나는 그것을 사용할 수 있다고 생각하지 않는다.

+1

'\. (png | jpg | gif) $'의 속도가 느린 이유는 정규식을 사용하면 가장 간단하다고 생각하기 때문입니다. 나머지는 구현에 달려 있습니다. – adamse

+2

왜 유효한 확장 배열을 반복하고 ['.EndsWith'] (http://msdn.microsoft.com/en-us/library/system.string.endswith (VS.71) .aspx)를 사용하십시오. ? 간단한 문자열 비교는 정규식 엔진보다 훨씬 빠릅니다. – kennytm

+0

얼마나 빨라야합니까? Ruby에서 가장 느린 언어 중 하나인데, 초당 348,000 개의 경로를 비교할 수 있습니다. 나는 더 빠르고 더 읽기 쉽고 이해하기 쉽기 때문에 더 간단한 정규 표현식을 택할 것입니다. –

답변

13

C#에 액세스 할 수 없으므로이 방법을 사용할 수는 없지만 엔진에서 문자열의 끝을 찾은 다음 확장을 일치 시키면 너무 많은 역 추적을 피할 수 있어야합니다.

$(?<=\.(gif|png|jpg)) 

성능 저하에 대한 영향은 확실하지 않습니다.

정말
+0

나의 예비 테스트에서, 이것은 내가 사용했던 접근 방식보다 약 2 배 빠르며, 테스트 애플리케이션에서 RightToLeft 매칭과 비슷한 수준이다. 본질적으로 수식을 RightToLeft로 쓰고 있기 때문에 그것이 맞는 것 같습니다. – NowYouHaveTwoProblems

+0

알겠습니다. 나는 몇몇 정규식 엔진이'$ '앵커를 볼 때 컴파일 단계에서 최적화를 할 것이라 확신하지만 문자열의 끝에서 검사를 시작하도록 확실히하고 있지만 분명히.NET 정규 표현식 엔진은 그렇지 않습니다. – Blixt

+5

나는 누군가가 내 대답을 downvoted 알았지 만, 이유를 설명하는 상관 없어 ... 그런 종류의 downvote 무의미한하게하지, 안 그래? 왜 항상 downvote 뭔가 설명하십시오. – Blixt

1

당신은 아마 이것에 대한 정규 표현식이 필요합니다 ...하지만 원래의 질문으로 진행하지 않습니다

당신이 할 RegexOptions.Compiled을 사용하고 있는지 확인 정규 표현식을 미리 컴파일 한 다음 정규식을 재사용 목적. 이렇게하면 RegEx를 사용할 때마다 설정을하지 않아도되므로 작업 속도가 빨라집니다.

+0

@NowYouHaveTwoProblems : SoapBox의 솔루션을 테스트하고 귀하의 접근 방식과 비교하는 방법을 알려주십시오. – lmsasu

+1

그는'RightToLeft' 옵션을 보낼 수 없으므로'Compiled' 옵션으로 보낼 수 없습니다. – Blixt

+0

@Blixt가 바로 여기에 있습니다. 내가 할 수있는 것은 먼 쪽에서 정규 표현식으로 해석 될 문자열을 전달하는 것입니다. – NowYouHaveTwoProblems

2

코드를으로 변경할 수있는 이유는 무엇입니까? API를 제어하지는 않지만, 어쨌든 API를 변경하려고합니다. 이것은 정말로 이해하지 못합니다.

어쨌든, 왜 단순히 :

var AcceptedExtensions = new List<string>() { "txt", "html", "htm" }; 
var extension = filename.Substring(filename.LastIndexOf(".") + 1).ToLower(); 
return AcceptedExtensions.Contains(extension); 

IEnumerable에서 AcceptedExtensions 일부 설정에서로드 할 것 같은 방법으로 당신은 당신의 jpg|gif|...를로드합니다. 또는 그것은 무엇이든간에 상수가 될 것입니다. 당신은 그것을 사용할 때마다 그것을 다시 만들 필요가 없습니다. (이것이 병목 현상이 될지는 의문입니다.)

+3

그래, 그렇게 할 수있는 확실한 방법이지만, 정규식으로 처리되는 문자열을 사용하는 API가 필요합니다. – Blixt

+0

사실, 나는 정규 표현식이 아닌 문자열 기반 접근법을 사용할 수 있기를 원하지만,이 경우에는 그 옵션을 가지고 있지 않습니다. – NowYouHaveTwoProblems

+0

옵션이없는 이유는 무엇입니까? 하나의 옵션은 위의 코드입니다. 왜 그것을 사용할 수 없습니까? –

3

것은 확장 이전 모든 문자 대신 기간 동안 특별히 보이게 :

\.(png|jpg|gif)$ 

이 그것을 안전 (x.xgif 일치하지 않습니다) 할 것입니다 그것은에 어떤 역 추적을 할 필요가 없습니다 모든 시간이 발견 될 때까지 (모든 캐릭터를 역 추적하는 것과는 대조적으로).

+0

원본 정규식에는 문자 그대로 점이 있지만 여기에 게시하면 마크 업에서 손실됩니다. – NowYouHaveTwoProblems

5

, 당신은 또한 단지 다음과 같이, 모두 정규식을 삭제하고 String.EndsWidth을 사용할 수

var extensions = new String[] { ".png", ".jpg", ".gif" }; 
extensions.Any(ext => "something".EndsWith(ext)); 

을 나는 보통 느낌이가이 오히려 같은 경우에 간단한 문자열 함수를 사용하는 것이 더 빠릅니다되는 것을 포기 끝나는 당신이 편안하고 Regex의 관점에서 효율적인 점을 알지 못한다면, 런타임 및/또는 개발 시간 측면에서 효율적인 정규 표현식을 사용하는 영리한 방법을 찾으려고 시도하는 것보다 훨씬 쉽습니다.

+5

아마도, 너무 지나치게 편향된 것 같습니다. Regex는 실제로 당신의 두뇌를 따라 잡으려고하는 사악한 레프리콘입니다. –

+0

누구나이를 확인/검증 할 수있는 벤치 마크가 있습니까? – Brad

관련 문제