2011-03-19 3 views
1

다양한 문자열을 구문 분석하고 접두사, 숫자 및 접미사를 결정해야합니다. 문제는 문자열이 다양한 형식으로 제공 될 수 있다는 것입니다. 나를 구문 분석하는 방법에 대해 생각하는 가장 좋은 방법은 문자열에서 가장 긴 숫자를 찾은 다음 그 전의 모든 것을 접두어로 사용하고 이후의 모든 것을 접미어로 사용하는 것입니다.문자열에서 가장 긴 숫자 목록을 구문 분석 할 수있는 RegEx가 있습니까?

몇 가지 예 :

0001   - No prefix, Number = 0001, No suffix 
1-0001  - Prefix = 1-, Number = 0001, No suffix 
AAA001  - Prefix = AAA, Number = 001, No suffix 
AAA 001.01 - Prefix = AAA , Number = 001, Suffix = .01 
1_00001-01 - Prefix = 1_, Number = 00001, Suffix = -01 
123AAA 001_01 - Prefix = 123AAA , Number = 001, Suffix = _01 

문자열은 접두사와 접미사의 혼합물로 올 수 있지만, 중요한 점은 숫자 부분이 항상 자리의 가장 긴 연속 목록입니다.

나는 이러한 예제 전부는 아니지만 대부분의 경우 작동하는 다양한 RegEx를 사용해 보았습니다. 제가 뭔가를 놓친 것일 수도 있고, 아니면 RegEx가이 경우 올바른 방법이 아닐 수도 있습니다.

은 (정규식은 .NET 호환되어야합니다)

UPDATE :

var regex = new System.Text.RegularExpressions.Regex(@"(\d+)"); 
if (regex.IsMatch(m_Key)) { 
    string value = ""; 
    int length; 
    var matches = regex.Matches(m_Key); 
    foreach (var match in matches) { 
     if (match.Length >= length) { 
      value = match.Value; 
      length = match.Length; 
     } 
    } 
    var split = m_Key.Split(new String[] {value}, System.StringSplitOptions.RemoveEmptyEntries); 
    m_KeyCounter = value; 
    if (split.Length >= 1) m_KeyPrefix = split(0); 
    if (split.Length >= 2) m_KeySuffix = split(1); 
} 
+1

123AAA 001_01 - 접두어 = 123AAA, 번호 = 001, 접미사 = _01' <- 여기서 접두어 "123"의 숫자는 해당 번호 인 "001"만큼 길다. 그들을 구별 할 길이 없습니다. – polemon

+0

좋은 지적. 필자는 12AAA 만 수행하도록 테스트 케이스를 수정했기 때문에 이러한 값이 발생할 가능성은 매우 낮습니다. 그렇다면 가장 긴 숫자가 아닌 가장 긴 숫자를 선택합니다. –

답변

2

맞아,이 문제는 순수한 정규식으로는 해결할 수 없습니다. 정규 표현식을 사용하여 입력을 "토큰 화"(어휘 분석) 할 수 있지만 이후에는 추가 처리 (구문 분석)가 필요합니다.

이 경우 입력을 토큰 화 (예 : 간단한 정규 표현식 검색 (\d+)) 한 다음 토큰 (구문 분석)을 처리합니다. 현재 토큰이 이전에 본 토큰보다 긴지 확인해야합니다.

정규 표현식을 "해결"하고 구문 분석이 필요할 때 특히 정규식이 컴파일러의 구성에 사용될 때 (예 : http://en.wikipedia.org/wiki/Book:Compiler_construction) 일반적인 컴파일러 이론을 확인하고자 할 수 있습니다.

+0

(\ d +) 검색은 첫 번째 숫자 시퀀스를 찾지 않습니까? 이용 가능한 모든 서열을 어떻게 찾았습니까? –

+0

Regex.Matches를 사용하는 경우가 아닙니다. 입력에서 일치 항목의 모음을 반환합니다. – steinar

+0

"(\ d +)"로 RegEx.Split()을 수행하면 문자열을 분리하고 가장 긴 숫자를 찾을 수있게되어 멋지게 보입니다. –

1

당신은 입력 ISN 위치 : 관심이 그 사람들을 위해, 여기에 내가 해낸 C# 코드가 있어요 그래서 정규식은하지 않습니다. (\ d +)를 통해 모든 숫자 그룹을 반복하고 가장 길게 찾은 다음 접두어/접미사를 찾으려면 (.*)<number>(.*)의 형식으로 새 정규식을 작성하십시오.

문자열 작업에 익숙하다면 대상 그룹의 시작과 끝을 찾고 substr을 사용하여 pre/suf 수정을 찾을 수 있습니다.

0

나는 당신이 하나의 정규식으로 이것을 할 수 있다고 생각하지 않는다. 나는 문자열 내의 모든 숫자 시퀀스 (아마도 정규식 포함)를 찾은 다음 .NET 코드로 가장 길게 선택하고 Split()을 호출합니다.

0

이것은 Regexp 엔진에 전적으로 달려 있습니다. 캡처를 위해 Regexp 환경을 확인하십시오. Perl의 자동 변수와 같은 항목이있을 수 있습니다.

OK,의 귀하의 질문에 대해 이야기하자

명심 모두 그, NFA와 DFA의 거의 모든 정규 표현식 엔진이다 욕심이 의미하는 (\d+)는 항상 가장 긴 일치를 찾을 것, 때를 "넘어지다".

지금, 나는 당신의 예에서 얻을 수있는, 당신은 항상 숫자의 중간 부분이 필요하고,이 시도 :

/^(.*\D)?(\d+)(\D.*)?$/ig 

지금 변수 $1, $2, $3 봐. 그들 모두가 존재하지는 않을 것입니다 : 그들 모두 3 개가 있다면, $2은 당신의 번호를 붙잡고, 다른 병들, 접두어의 부분들입니다. 접두사 중 하나가 누락되면 변수 $1$2 만 설정되고, 어느 것이 정수인지 직접 확인해야합니다. 접두어와 접미사가 모두 누락 된 경우 $1이 번호를 보유합니다.

아이디어는 엔진을 처음 몇 글자 이상으로 "비틀 거리게"만들고 중간에 긴 숫자와 일치시키기 시작하는 것입니다.

수정 자 /g이 있기 때문에 컴퓨터에서 찾은 사용 가능한 모든 조합을 반복 할 수 있습니다. 그러면 가장 좋아하는 것을 취할 수 있습니다.

이 예제는 PCRE에 있지만 .NET에는 호환 모드가 있습니다.