2011-02-14 3 views
15

Regex.Replace 호출이 수행하는 대체 횟수를 계산하는 방법이 있습니까?Count regex (C#)

예. Regex.Replace("aaa", "a", "b");에 대해 숫자 3을 얻고 싶습니다 (결과는 "bbb"입니다). Regex.Replace("aaa", "(?<test>aa?)", "${test}b");에 대해 숫자 2를 얻고 싶습니다 (결과는 "aabab"입니다).

방법 나는이 할 생각 할 수 있습니다

  1. 는 대체 수동
  2. 을하고, 촬영 된 변수를 증가 MatchEvaluator를 사용을을 MatchCollection를 확인하고 수동으로 교체를하고 카운트
  3. 을 유지, 그것을 반복
  4. 검색 제 1 및 제을 MatchCollection를 얻을 것과 카운트를 얻을 후 별도의는

방법 1과 2는 대체 $의 수동 분석을 필요로 대체 할 메소드 3은 문자열을 두 번 일치시키는 정규 표현식을 요구합니다. 더 좋은 방법이 있습니까?

+0

이것은 정규식 검색으로 호출하여 패턴을 명령 줄 인수로 대체 할 수있는 간단한 명령 줄 유틸리티입니다. 그래서 이상적으로 패턴에 대한 지식을 미리 알지 못하는 일반 솔루션이 필요합니다. 정말로 이것이 관심사이지만 - 닷넷에서 이것을하는 가장 좋은 방법은 무엇입니까? $ replacement의 수동 구문 분석과 함께 MatchEvaluator 접근 방식이 앞으로 나아갈 것으로 보이지만 약간 지저분합니다. ( –

+0

Simon, 내 편집 참조 – Chev

답변

13

Chevex와 Guffa에게 감사드립니다. 결과를 얻는 더 좋은 방법을 찾기 시작했고 대체를 수행하는 Match 클래스에 Result 메서드가 있다는 것을 알게되었습니다. 그것이 퍼즐 조각이없는 부분입니다. 하기 실시 예 번호 : 파일 TEST.TXT 함유 AAA와

using System.Text.RegularExpressions; 

namespace regexrep 
{ 
    class Program 
    { 
     static int Main(string[] args) 
     { 
      string fileText = System.IO.File.ReadAllText(args[0]); 
      int matchCount = 0; 
      string newText = Regex.Replace(fileText, args[1], 
       (match) => 
       { 
        matchCount++; 
        return match.Result(args[2]); 
       }); 
      System.IO.File.WriteAllText(args[0], newText); 
      return matchCount; 
     } 
    } 
} 

명령 행 regexrep test.txt "(?<test>aa?)" ${test}b은 2 % ERRORLEVEL % 설정 aabab 텍스트를 변경한다.

+1

(일치하는 항목)은 유형이 내포 된 변수 이름 "match"로 단순화 될 수 있습니다. – Chev

+0

감사합니다. Chevex, edited. –

+0

나는 match 객체에 대한 Result() 메소드를 알지 못했다. Replace() 작업을 수행하면서 각 일치 항목에서 일부 기능을 실행하는 것이 빠르고 쉽습니다. 좋은 일 사이먼. – Chev

3

이렇게해야합니다.

 int count = 0; 
    string text = Regex.Replace(text, 
      @"(((http|ftp|https):\/\/|www\.)[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?)", //Example expression. This one captures URLs. 
      match => 
      { 
       string replacementValue = String.Format("<a href='{0}'>{0}</a>", match.Value); 
       count++; 
       return replacementValue; 
      }); 

나는 내가 지금 당장 할 수 없습니다 내 dev에 컴퓨터에 아니지만, 나중에 실험 람다 표현식이 작업을 수행하는 방법이 아닌 방법을 선언이 있는지 확인하기 위하여려고하고있다 IncrementCount() int를 증가시킵니다.

EDIT은 다른 방법을 선언하는 대신 람다 식을 사용하도록 수정되었습니다.

EDIT2 패턴을 미리 알지 못하더라도 일치 객체에 포함 된 모든 그룹 (참조하는 $ 그룹)을 GroupCollection에 포함시킬 수 있습니다. 그래서 같이 : 당신이 생산 가지고

int cnt = 0; 
string result = Regex.Replace("aaa", "a", m => { 
    cnt++; 
    return "b"; 
}); 

두 번째 사건은 까다 롭습니다 :

 int count = 0; 
    string text = Regex.Replace(text, 
      @"(((http|ftp|https):\/\/|www\.)[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?)", //Example expression. This one captures URLs. 
      match => 
      { 
       string replacementValue = String.Format("<a href='{0}'>{0}</a>", match.Value); 
       count++; 
       foreach (Group g in match.Groups) 
       { 
        g.Value; //Do stuff with g.Value 
       } 
       return replacementValue; 
      }); 
+0

이 작업은 (감사합니다!) 근본적으로 제 방법 1입니다.일반 입출력에서 작동하게하려면 교체에서 $ {test}를 구문 분석해야하므로 더 복잡한 작업이 필요합니다 ("$ 치환의 수동 구문 분석"참조). –

+0

일치 개체에는 $ 그룹이 첨부 된 GroupCollection으로 포함됩니다. 표현을 미리 모르고 포함될 그룹의 수를 모르는 경우 my EDIT2와 같은 그룹 콜렉션을 반복하십시오. 나는 대답의 그룹 가치와 아무 것도하지 않지만 어떻게 할 수 있는지 쉽게 알 수 있어야합니다. – Chev

7

당신은 당신이 발생하는 횟수를 셀 수 그런 식으로 각각의 교체를 실행하는 MatchEvaluator을 사용할 수 있습니다 대체 패턴과 동일한 결과는 다음과 같습니다.

int cnt = 0; 
string result = Regex.Replace("aaa", "(?<test>aa?)", m => { 
    cnt++; 
    return m.Groups["test"] + "b"; 
}); 
+1

그리고 여기 내 대답에 해당하는 람다가 있습니다 : 3 – Chev

+1

@Chevex : 코드를 먼저 테스트 했으므로 답장을 좀 더 오래 걸렸습니다. ;) – Guffa

+0

Chevex의 대답에 대한 내 의견보기 - 패턴을 미리 알고있는 경우에만 작동합니다. 그렇지 않으면 regex replace 문자열을 구문 분석해야합니다. –