1

長い文字列に対して正規表現の一致を実行するパターンを見つけようとしています。一致が見つかるたびに、置換が実行されます。問題は、一致した値によって置換が異なるということです。この新しい値はメソッドによって決定されます。例えば:

var matches = Regex.Match(myString, myPattern);
while(matches.Success){
   Regex.Replace(myString, matches.Value, GetNewValue(matches.Groups[1]));
   matches = matches.NextMatch();
}

問題 (私が思うに) は、Regex.Replace を実行すると、すべての一致インデックスが台無しになり、結果が間違ってしまうことです。助言がありますか?

4

3 に答える 3

4

各パターンを固定文字列に置き換えると、それが行わRegex.replaceれます。一致を繰り返す必要はありません。

Regex.Replace(myString, myPattern, "replacement");

そうではなく、置換が一致した値に依存する場合は、MatchEvaluatorデリゲートを の 3 番目の引数として使用しRegex.Replaceます。のインスタンスを受け取り、Matchを返しますstring。戻り値は置換文字列です。一部の一致を置き換えたくない場合は、単に次を返しmatch.Valueます。

string myString = "aa bb aa bb";
string myPattern = @"\w+";
string result = Regex.Replace(myString, myPattern, 
                      match => match.Value == "aa" ? "0" : "1" );
Console.WriteLine(result);
// 0 1 0 1

一致を反復して手動で置き換える必要がある場合は、最後の一致から最初の一致に向かって置換を開始して、次の一致で文字列のインデックスが台無しにならないようにする必要があります。次に例を示します。

var matches = Regex.Matches(myString, myPattern);
var matchesFromEndToStart = matches.Cast<Match>().OrderByDescending(m => m.Index);
var sb = new StringBuilder(myString);
foreach (var match in matchesFromEndToStart)
{
    if (IsGood(match))
    {
        sb.Remove(match.Index, match.Length)
          .Insert(match.Index, GetReplacementFor(match));
    }
}

Console.WriteLine(sb.ToString());

一致にネストされたインスタンスが含まれていないことに注意してください。その場合、別の一致内にある一致を削除するか、正規表現パターンを再実行して、置換ごとに新しい一致を生成する必要があります。私は引き続き、デリゲートを使用する 2 番目のアプローチをお勧めします。

于 2013-02-05T03:53:25.133 に答える
1

あなたの質問を正しく理解していれば、一定の正規表現に基づいて置換を実行したいと思いますが、使用する置換テキストは、正規表現が一致する実際のテキストに基づいて変更されます。

(Matchメソッドではなく)MatchクラスのCapturesプロパティは、入力文字列内の正規表現とのすべての一致のコレクションを返します。文字列内の位置、一致した値、一致の長さなどの情報が含まれています。foreachループを使用してこのコレクションを反復処理すると、各一致を個別に処理し、置換値を動的に変更できる文字列操作を実行できるはずです。

于 2013-02-05T04:01:53.010 に答える
0

私は次のようなものを使用します

Regex regEx = new Regex("some.*?pattern");
string input = "someBLAHpattern!";
foreach (Match match in regEx.Matches(input))
{
    DoStuffWith(match.Value);
}
于 2013-02-05T04:08:05.110 に答える