2010-03-07 2 views
10

욕심한다, 게으른 행동하지만, 다음과 같은 코드가 아닌 :정규식 나는 기본적으로 내 <strong>정규식</strong> 내가 원하는 욕심 동작이 발생할 것이라고 생각

Regex keywords = new Regex(@"in|int|into|internal|interface"); 
var targets = keywords.ToString().Split('|'); 
foreach (string t in targets) 
    { 
    Match match = keywords.Match(t); 
    Console.WriteLine("Matched {0,-9} with {1}", t, match.Value); 
    } 

출력 :

Matched in  with in 
Matched int  with in 
Matched into  with in 
Matched internal with in 
Matched interface with in 

지금 난 내가 단순히 길이 하강하여 키워드를 분류하는 경우는이 작은 예를 들어 작동시킬 수 있지만,

    수 있다는 것을 깨닫게 이 알파벳 순서로 유지하는 것이 중요합니다
  • 나는 예상대로이 가 작동하지 않는 이유를 이해하려면, 그리고
  • 내가 일하고 실제 프로젝트는 정규식에 더 많은 단어를 가지고 .

제 질문은 : 왜 이것이 게으름을 피우고 어떻게 수정합니까?

+0

실제 사용량이 더 복잡한 지 잘 모르겠지만 위의 예제가 실제로 수행하는 작업 인 경우 IndexOf 메서드와 일치하는 단어 목록을 반복하는 것이 천 번 더 좋을 것이라고 생각합니다 . 정규 표현식에 번갈아 단어 집합이 포함되어 있다면 성능이 떨어질 수 있습니다. – Josh

+0

@Josh - 아니, 예제가 단순화되었습니다. 실제 응용 프로그램은 렉서 및 문법 파서를 생성하기 위해 언어 파일을 읽는 중입니다. 내 정규 표현식에 녹슬지는 않은 것 같다. 내 문제가 너무 분명해 보인다! – Stomp

+0

@Josh : Regex 엔진은 공통 접두어와 일치하지 않는 많은 수표를 버리는 등 많은 경우에 최적화를 할 수 있습니다. 예를 들어, 첫 번째 문자가 "i"가 아닌 경우 "i"로 시작하는 분기가 확인되지 않습니다. .NET 엔진이이 작업을 수행하는지 확신 할 수는 없지만 그렇게하지 않으면 놀랄 것입니다. –

답변

12

게으름 탐욕은 한정사 (?, *, +, {min,max})에 적용된다. 교대는 항상 순서대로 매치되며 가능한 첫 번째 경기를 시도하십시오.

+0

+1, 탐욕에 대한 한정어가 있어야합니다. – codaddict

+0

재주문 이외의 옵션이 없습니까? Hrmmm ... 내가 순식간에 순서를 바꿀 수있어서 알파벳순으로 정의를 유지할 수있을 것 같습니다. – Stomp

+0

@Stomp : 예, 할 수 있습니다. 목록에 알파벳순으로 프로그램을 유지하고 실제로 적용하기 전에 길이별로 정렬 할 수 있습니다. – codaddict

3

RegularExpressions.info에 따르면 정규식은 eager입니다. 따라서 귀하의 piped expression을 통과 할 때 첫 번째 일치도에서 멈 춥니 다.

제 생각에는 모든 키워드를 배열이나 목록에 저장 한 다음 필요할 때 정렬 된 파이프 식을 생성하는 것이 좋습니다. 키워드 목록이 변경되지 않는 한이 작업을 한 번만 수행하면됩니다. 생성 된 표현식을 일종의 싱글 톤 (singleton)에 저장하고 정규식 실행시이를 리턴하십시오.

+0

@Jeras - 링크를 제공해 주셔서 감사합니다! 나는 MSDN에서 검색 중이었고 열망하여 첫 번째 경기를 찾고 싶었던 것 같습니다. – Stomp

6

단어 분리를 시도하는 것처럼 보입니다. 그렇게하기 위해서는 전체 표현이 정확해야하며, 현재 표현은 정확하지 않아야합니다. .. 대신 하나를 시도

new Regex(@"\b(in|int|into|internal|interface)\b"); 

은 "\ B는"단어 경계를 일치라고하고, 제로 폭 일치입니다. 이것은 로케일에 의존하는 동작이지만 일반적으로 이것은 공백과 구두점을 의미합니다. 너비가 일치하지 않으면 정규 표현식 엔진이 단어 경계를 감지하게하는 문자를 포함하지 않습니다.

+1

'\ b'를 추가하면 원하는 동작을 이끌어 낼 수는 있지만 작동 원리는 틀린 것입니다. '\ b'는'^','$', 그리고 lookarounds와 같은 제로 폭 (zero-width) 어서션이다; 문자를 매치하는 대신 문자 앞이나 뒤에 가상의 갭을 매치시킵니다. 첫 번째 또는 마지막 문자 (각각)가 단어 문자 인 경우 문자열의 시작 또는 끝은 자동으로 단어 경계가되므로 두 번째 정규식은 첫 번째 문자의 좀 더 자세한 버전입니다. –

+0

@Alan, 코드 실행을 시도했지만 분명히 옳습니다. 우리가하는 일을보기 위해 직장에서 코드를 다시 확인해야 할 것입니다. 아마 우리는 \ W를 사용하고 있고 \ b는 사용하지 않았을 것입니다. 나는 펑키 정오 캡처 그룹 설정을 알고있는 비슷한 상황에서 우리가 일종의 "단어가 아닌"문자를 얻고 있다는 것을 알고 있습니다. 로케일에 민감한 경우 구두점의 역할에 따라 단어 경계가 다르게 정의되므로이 경우가 될 것입니다. –

+0

@Alan, 귀하의 의견을 반영하여 답변을 수정했습니다. –

관련 문제