2012-02-13 3 views
3

받는 텍스트 파일을 구문 분석하는 프로젝트 작업 중입니다. 내가가는대로 C#을 배우고 있습니다. 현재 필요한 정보를 선택하는 방법은 다음과 같습니다.일치 및 정규식 작업

string MyMatchString = @"a pattern to match"; 
Match MyMatch = Regex.Match(somestringinput, MyMatchString); 
if (MyMatch.Succes) 
{ 
    DoSomething(MyMatch.Value); 
} 

나는 많은 것을하고 있습니다. 경기와 성공을 한 번에 결합 할 수 있기를 바랍니다. 클래스 목록을 살펴보면 Regex에는 IsMatch() 메서드가 있지만 일치하는 값에 액세스 할 수있는 것으로 보이지 않습니다 (성공적이라고 가정). 나는 그것에 대한 Match 인스턴스가 필요하다고 생각한다. 시도 :

if ((Match MyMatch = Regex.Match(somestringinput, MyMatchString).Success) 

물론 컴파일 오류가 발생했습니다.

나는 매치 패턴을 취한 정적 메소드를 생각하고있다. 그러면 입력은 bool을 반환한다. 그렇다면 나는 단지 성공을 시험 할 수 있습니다. 그렇다면 일치 된 가치를 얻으십시오. 당신은 선택적으로 당신은 단지 하나의 일치를 원하는 경우 break를 추가 (또는 .Take(1) 사용) 그냥 부울 값으로 답변을 원하는 경우에

+0

당신은 당신 자신의 질문에 대답했습니다 ... – Tudor

답변

1

그럼 당신은 당신에게 힘을 줄 것이다 정규식에 대한 확장 방법을 쓸 수 있습니다 : 당신은 당신이 이렇게 원하는 부울 값을 가져 Regex.Match를 사용할 수 있습니다. 트릭은 정규 표현식을 두 번 실행하지 않고 작업을 수행하는 것으로 성능에 문제가 될 수 있습니다 (참고 :이 테스트는 수행되지 않았으며 Regex 객체가 작동해야한다는 점에서 아이디어와 다릅니다).

public static class RegexExtensions { 
    public static bool GetMatch(this Regex regex, string input, out string matched) { 
     Match match = regex.Match(input); 
     if (match.Success) { 
      matched = match.Value; 
      return true; 
     } 
     matched = null; 
     return false; 
    } 
} 

그래서 당신은 당신은 단지 그렇지 않으면 실패 케이스와 문자열에 null을 반환하고 부울 및 출력 매개 변수를 생략하는 것을 선호 할 수

string matched; 
Regex regex = new Regex(pattern); 
if (regex.GetMatch(inputstring, matched)) 
{ /* do something with 'matched' */ } 
else 
{ /* no match, 'matched' is null */ } 

같은 일을 할 것입니다.

+0

+1 원본 코드의 의미를 약간 변경하지만 가장 우아한 접근 방법입니다. 정적 확장 메서드를 정의 할 수 없다는 것은 수치스러운 일입니다. – Tudor

+0

좋습니다. 이 접근법에서 볼 수있는 한 가지 문제점은 Match에서 얻은 모든 것이 단일 문자열 값이라는 것입니다. 특정 사용 사례에서는 괜찮을 지 모르지만 그다지 유연하지는 않습니다. 그가 정규식에서 두 개의 값을 원하면 어떻게 될까요? –

+0

이 접근법과 비슷한 점은 내가 생각하고있는 것입니다. foreach를 사용하여 이것을 조정할 수 있고 여러 일치 문자열을 반환 할 수 있습니다. MatchCollection에 대한 오버로드 또는 오버로드. 또한 C#이 참조 형식을 참조로 전달하기 때문에 문자열을 반환하는 대신 bool 반환 값을 테스트하려고했습니다. RegEx 대신 Match에서 패스합니다. 반환 유형이 bool이고이 메서드를 실행하고 일치가 성공하면 전달 된 일치 항목이 일치 항목의 결과를 가리 키도록 변경됩니다. –

3

변수 일치를 사용하여 저장하십시오.

if (Regex.Match("a", MyMatchString).Success) { }; 
0

을 foreach는

string MyMatchString = @"a pattern to match"; 
foreach (Match match in Regex.Matches(somestringinput, MyMatchString)) 
{ 
    DoSomething(match.Value); 
} 

를 사용하고 그나마 저장할 해달라고

+0

왜 그 경우에는 IsMatch를 사용하지 않는 것이 좋습니까? –

+0

그는 그것을 사용할 수 있습니다. – NoviceMe

1

TryParseTryGetValue이 사용하는 "시도"규칙을 구현할 수 있습니다.

public static bool TryMatch(string input, string pattern, out Match match) 
{ 
    var m = Regex.Match(input, pattern); 
    if(m.Success) 
    { 
     match = m; 
    } 
    return m.Success; 
} 

// usage 
string myMatchString = @"a pattern to match"; 
Match result = null; 
if(TryMatch(somestringinput, myMatchString, out result)) 
{ 
    DoSomething(result.Value); 
} 

또는, ActionFunc 위임을 받아 higher-order 함수를 만들 수 있습니다.

public void ActionOnMatch(string input, string pattern, Action<string> action) 
{ 
    var m = Regex.Match(input, pattern); 
    if(m.Success) 
    { 
     action(m.Value); 
    } 
} 

public TResult FuncOnMatch<TResult>(string input, string pattern, 
    Func<string, TResult> func) 
{ 
    var m = Regex.Match(input, pattern); 
    if(m.Success) 
    { 
     return func(m.Value); 
    } 
    else 
    { 
     return default(TResult); 
    } 
} 

/// usage 
string pattern = @"a pattern to match"; 
ActionOnMatch(input, pattern, DoSomething); 
var result = FuncOnMatch<string>(input, pattern, (val) => val); 
0

일치 항목을 만들면 성공 여부를 테스트하고 결과를 사용하는 것이 디자인 상 별도의 단계입니다. 그 주위에는 여러 가지 방법이있을 수 있지만 프레임 워크와 싸우고 코드를 약간 작게 만드는 것이 좋습니다 다른 개발자가 읽을 수있는 코드는입니다.

파일을 구문 분석하는 경우에는 Linq를 사용하는 다른 방법을 고려할 수 있습니다. DoSomething이 무엇을 의미하는지에 따라 최소한 코드가 약간 지루할 수 있습니다.

Regex re = new Regex(@"(?<prop1>pattern part 1)(?<prop2>pattern part 2)"); 

var goodLines = 
    from line in File.ReadAllLines(inputFile) 
    let m = re.Match(line) 
    where m.Success 
    select new { 
     Prop1 = m.Groups["prop1"].ToString(), 
     Prop2 = m.Groups["prop2"].ToString() 
    } 

foreach (var goodLine in goodLines) { 
    DoSomething(goodLine); 
} 

는 여기에서 우리는 정규식 내 이름을 캡처 그룹을 정의하고, 익명의 유형을 채우기 위해 그 이름을 캡처를 사용하고 있습니다. 그런 다음 Linq 표현식에 의해 반환 된 익명 객체 컬렉션을 반복합니다.

+0

LINQ에 대해 생각했지만 파일의이 섹션에서 내가 검색 한 3 개의 일치 항목이 있습니다. 하나를 찾으면 3 가지 다른 것들 중 하나를 수행하며, 모두 더 많은 일치를 포함합니다. 나는 3의 각각에 대해 괴물 성냥을 쓸 수 있었지만 (그리고 가질 수는있다.) 그러나 패턴을 얻기가 어렵다. 특히 패턴이 생길 수도 있고 그렇지 않을 수도있다. –

+0

최상위 패턴을 찾으면 일치시킬 하위 수준 패턴이 있습니다. 가능한 20 라인을 일치시키는 Regex를 작성하는 것은 좋은 생각이 아닙니다. 별도의 LINQ 문은 하위 수준 일치가 최상위 수준과 일치 함을 보장하지 않습니다. –