1

二重中括弧の間のすべての文字を一致させる必要がありますが、1 つの大きな文字列で複数の一致を見つけることができる必要があります。

私は C# でこれを行っているため、この RegEx テスターを使用しています : http://derekslager.com/blog/posts/2007/09/a-better-dotnet-regular-expression-tester.ashx SingleLine」が欲しいのでチェック。一致する \n

これが私が一致している文字列の例です:

<div class="nest-1-2">
    <dl>
    <dt>Type:</dt>
    <dd>{{(Entity)Field Name.separator(, ) > [:Name:]}}</dd>
    <dt>At:</dt>
    <dd>{{(Entity)Field Name > [:Name:]}}</dd>
    <dt>Team:</dt>
    <dd>{{(Entity)Field Name.separator(, ) > [:First Name:] [:Last Name:]}}</dd>
    </dl>
</div>

私が使用している正規表現は次のとおりです。

\{\{(?<field>[^>]*)?[ > ]?(?<looptemplate>[^\}\}].*)?\}\}

私が抱えている問題は、すべてのテキストを次の }} まで一致させたいということです。これは、次のテキストではなく最後のテキストと一致しています。だから私は否定的な先読みを使用しようとした最初{{から最後までのすべてである1つの一致を取得していますが、それは私にとってはうまくいかないようです. 残念ながら、 は両方の中括弧には一致せず、一方のみに一致します。}}(?!\}\})[^\}\}]

私は正規表現の完全な初心者ではありませんが、これは本当に私を魅了しました. 私は答えを見つけようとして周りを見回したので、誰かが私を助けてくれることを願っています.

専門家からの助けを本当に感謝します。

4

4 に答える 4

5

いくつかのこと:

  1. ?を含むキャプチャ グループで使用していました**は「0回以上」という意味なので、基本的に内容はすでに任意です。使用しても何も起こり?ません。

    \{\{(?<field>[^>]*)[ > ]?(?<looptemplate>[^\}\}].*)\}\}
    
  2. [ > ]1文字に一致します。スペースまたは>. おそらく、(?: > )(これは一致" > "します (引用符を無視します。そうしないと、SO はスペースをレンダリングしません) を意味し、それをグループ化します。

    \{\{(?<field>[^>]*)(?: > )?(?<looptemplate>[^\}\}].*)\}\}
    
  3. [^\}\}]と同じ[^\}]です。否定された文字クラスは文字列では機能しません。それらは内部のすべての個々の文字でのみ機能するため、複数回書いても何も変わりません。それがあなたが否定的な先読みを試みた理由だと思います。これは正しいですが、繰り返しのすべての文字についてその条件を確認する必要があります。looptemplateそれ以外の場合は、が で始まっていないことを一度だけ確認しますが\}\}、 で発砲し.*ます。したがって、グループ.化と先読みを一緒にします。

    \{\{(?<field>[^>]*)(?: > )?(?<looptemplate>(?:(?!\}\}).)*)\}\}
    
  4. あなた(?: > )はオプションなので、それを{{...}}含まないものがある場合(field以前と同じ問題が発生する部分しかありませんが、今回は[^>].ここにも先読みを含めます:

    \{\{(?<field>(?:(?!\}})[^>])*)(?: > )?(?<looptemplate>(?:(?!\}\}).)*)\}\}
    

ところで、否定された文字クラスまたは先読みを使用する代わりに、貪欲でない繰り返しを使用することができます。否定された文字クラスを使用できる場合は、通常はそれが望ましいです。これは、バックトラックが必要ないため、貪欲でない修飾子よりも通常は効率的ですが、同じように読みやすいためです。あなたの場合、先読みを使用する必要があります(1文字だけではなく、過去に行きたくない2つの連続した文字のパターンがあるため)。その場合、先読みはバックトラッキングを回避することによるパフォーマンスの向上を相殺する可能性があり、さらに通常、先読みは少し読みにくくなります。したがって、ここで貪欲でない繰り返しを使用したい場合があります (繰り返し量指定子を で追加します?)。

\{\{(?<field>(?:(?!\}})[^>])*)(?: > )?(?<looptemplate>.*?)\}\}

はオプションでfieldあるため、貪欲でない繰り返しを使用できないことに注意してください。(?: > )それはfield空であり、他のすべて( と" > "一致する可能性のあるものを含むlooptemplate>looptemplate

\{\{(?<field>[^>]*?)(?: > (?<looptemplate>.*?))?\}\}

最後に 1 つ。これは好みの問題ですが、別の逃げ方を紹介しましょう。多くのメタ文字は、文字クラス内ではメタ文字ではありません ( ]-^およびのみ\です)。したがって、メタ文字を文字クラスでラップしてエスケープできます。

[{][{](?<field>[^>]*?)(?: > (?<looptemplate>.*?))?[}][}]

私が言ったように、単なる提案ですが、ほとんどの文字では、バックスラッシュを使用するよりも読みやすいと思います.

于 2012-12-12T21:56:50.997 に答える
2

また、欲しいので「SingleLine」にチェックを入れています。一致する \n

「Single line」のチェックを外すと動作します。だから明らかにあなた.が問題です。簡単な解決策は、できるだけ貪欲に選択するのではなく、必要なだけ貪欲に選択しない.*?代わりに使用することです。別の解決策は、おそらくその内部の別のものと一致させたくないので、否定的な先読みなど、より具体的なもの.*に置き換えることです(または)。しかし、この場合、貪欲でない解決策ははるかに簡単です。.{{}}

おそらく、フィールド文字クラスの乗法子も変更して、すでにループ テンプレートの一部になっているものと一致しないようにする必要があります。

[ > ]また、スペースまたは のいずれかを選択する文字クラスであることに注意してください>。したがって、選択しません" > "。それが必要な場合は、括弧を外したままにしてください:

\{\{(?<field>[^>]*?)? > (?<looptemplate>[^}].*?)?\}\}

あなたの場合、おそらく looptemplate のことをオプションにしたいので、おそらく非キャプチャグループで次のようにしたいと思うでしょう:

\{\{(?<field>[^>]*?)?(?: > (?<looptemplate>[^}].*?))?\}\}

また、最後に 1 つ注意してください。.改行を一致させたい場合は、必要に応じて例を提供してください。

(わかりました、別のメモ、m.buettnerが彼の回答で正しく述べたように、文字クラスは各文字を1回だけ言及する必要があります。さらに、文字クラス内の中括弧をエスケープする必要はないため、すべて単純化されます[^}]

于 2012-12-12T22:02:59.517 に答える
0

これはどうですか:

\{\{.*?\}\}

.*?に似て.*いますが、貪欲ではなく遅延マッチングを採用しています。つまり、正規表現の残りの部分に進む前に可能な限り消費しようとする貪欲なマッチングではなく、マッチングを停止し、残りの正規表現のマッチングをできるだけ早く継続しようとします。

したがって、「{{this}} and that}}」に適用されます

\{\{.*?\}\}「{{this}}」に一致

\{\{.*\}\}「{{this}} and that}}」に一致

于 2012-12-12T21:54:58.177 に答える
0

編集開始:

さて、テキストファイルを変更しました....

<div class="nest-1-2">
    <dl>
    <dt>Type:</dt>
    <dd>{{(Entity)Field Name.separator(, ) > [:Name:]
    foo came up
    boo is here too}}</dd>
    <dt>At:</dt>
    <dd>{{(Entity)Field Name > [:Name:]}}</dd>
    <dt>Team:</dt>
    <dd>{{(Entity)Field Name.separator(, ) > [:First Name:] [:Last Name:]}}</dd>
    </dl>
</div>

そして、正規表現の新しいコンストラクターにパラメーターを追加しました...皮肉なことに、オプションは「SingleLine」です

System.Text.RegularExpressions.Regex Y = new System.Text.RegularExpressions.Regex("{{(.*?)\\}}", System.Text.RegularExpressions.RegexOptions.Singleline);

編集の終了 .... ... ...

テスト用に、例の文字列をコピーしてフラット テキスト ファイルに貼り付けます。

namespace a
{
    class Program
    {
        static void Main(string[] args)
        {
            string X = System.IO.File.ReadAllText("C:\\Users\\rnirnberger\\Documents\\a.txt");
            System.Text.RegularExpressions.Regex Y = new System.Text.RegularExpressions.Regex("{{(.*?)\\}}");
            System.Text.RegularExpressions.MatchCollection Z = Y.Matches(X);
            foreach (System.Text.RegularExpressions.Match match in Z)
            {
                Console.WriteLine(match.Value);

                //If you want to strip out the double-braces
                //↓↓↓↓

                //Console.WriteLine(match.Value.Replace("{{", "").Replace("}}", ""));
            }
        }
    }
于 2012-12-12T21:57:10.940 に答える