1

「制御シーケンス」を含む html がいくつかあります。既にコンテンツから html タグを削除しています。「制御シーケンス」を「スタイル」に変換したいと考えています。

HTMLタグが削除された後、私はこれを持っています...

"<!C43!><!TG!>Some Characters"

最終的にこれを作成するには...

<span class="C43 TG">Some Characters</span>

これまでのところ、私の欠陥のあるc#:

Regex reg = new Regex("<!([^<>]+?)!>");

Match matches = reg.Match(line);
foreach (Group group in matches.Groups)
{
    // finds both groups,
    // and remove the control sequence
}

「foreach」にはまだ多くの情報がありません。これは、breakboint で検査すると、次のグループが誤って返されるためです...

Group 1 : <!C43!>
Group 2 : C43
<it does not find second group :( >

どんな助けでも大歓迎ですが、私は主に文字列で探しているものを見つけるための正しい正規表現を探していますが、正規表現ライブラリでも役に立たないので、最も効果的な「グループの検索、グループの保存」 、検索している文字列からグループを削除することも大歓迎です。

4

3 に答える 3

3

あなたは間違ったことをループしています。これを試して:

string line = ...;
Regex reg = ...;
for (var match = reg.Match(line); match.Success; match = match.NextMatch())
{
    // in here, don't bother with .Groups... you don't need it
}
于 2013-06-06T16:23:04.450 に答える
2

他の人が言ったように、パターンには 1 つのグループしかないため、s ではMatchなく esをループする必要があります。Groupこれを行う通常の方法は、Michael Gunter のforループまたは単に

Match m = reg.Match(line);
while(m.Success)
{
    // read class from m.Groups[1]
    m = m.NextMatch();
}

ただし、最終的な問題を解決するには、すべてのデータを個別に取得して文字列を元に戻すのは少し面倒かもしれません。特に、この置換を複数行で一度に行いたい場合はなおさらです。

Regex.Replaceしたがって、 (コールバックを受け取るバージョン)を調べることをお勧めします。そうすれば、すべてを 1 回の一致で一致させることができ、.NET の独自の機能を利用して、1 つのグループの複数のキャプチャにアクセスできます。

var line = "<!C43!><!TG!>Some Characters";

MatchEvaluator evaluator = new MatchEvaluator(ReplaceCallback);

string output = Regex.Replace(
    line,
    @"(?:<!([^<>]+)!>)+(.+)",
    evaluator
);

そしてあなたのクラスのどこかで:

static string ReplaceCallback(Match match)
{
    var sb = new StringBuilder("<span class=\"");
    sb.Append(match.Groups[1].Captures[0].Value);
    for(int i = 1; i < match.Groups[1].Captures.Count; i++)
    {
        sb.Append(" ");
        sb.Append(match.Groups[1].Captures[i].Value);
    }
    sb.Append("\">");
    sb.Append(match.Groups[2].Value);
    sb.Append("</span>");
    return sb.ToString();
}

文字列を設定する方がおそらく簡単ですString.Formatが、現時点でString.JoinCaptureCollection.

だから、これは基本的に何をしているのか:

パターン@"(?:<!([^<>]+)!>)+(.+)"は 1 つ以上の<!...!>「トークン」に一致し、次に行の残りの部分に一致します。そうしている間に、の内容をキャプチャし<!...!>ます。繰り返しごとに別のキャプチャが記録され、後でコールバックでそれらすべてにアクセスできます。トークンの後、<!...!>行の残りを で照合してキャプチャし(.+)ます。文字列の前にあることに注意してください@: これにより、文字列が逐語的に作成されます。これは、正規表現パターンを指定するときに常に行う必要があります。そうしないと、エスケープに関して問題が発生します。?:また、最初の左括弧の後に注意してください。<!これは、区切り文字を含む別のキャプチャが必要ないため、キャプチャを抑制するためです!>。実際にキャプチャする必要がない限り、常に非キャプチャ グループを使用することも良い方法です。

コールバック関数は、入力の一致ごとに呼び出されます。行全体を含む一致は 1 つだけです。この試合では、 group で 2 つのトークンがキャプチャされ1、残りの行は group でキャプチャされました2

したがって、 で始まる文字列を簡単に作成できます。次に、 <span ="group のすべてのキャプチャのスペース区切りリスト、1次に">キャプチャされた残りの行、最後に</span>.

先ほど言ったようにString.Join、コレクション グループへの道を見つけると、コールバック関数は 3 行ほどに減ります。

Matchの区別がまだ少し曖昧な場合は、コールバック関数にブレークポイントを設定し、そこでオブジェクトを調べることをお勧めします。GroupCapturematch

于 2013-06-06T16:43:44.577 に答える
0

RegexHero で問題を再現できません:

http://www.regexhero.net/tester

2 つのグループを次のようにキャプチャします。

1: C43
1: TG

あなたの入力は、あなたが期待するものであると確信していますか? 結果のために意図したコレクションを繰り返していますか?

于 2013-06-06T16:22:28.440 に答える