5

このテキスト入力があるとしましょう。

 tes{}tR{R{abc}aD{mnoR{xyz}}}

ff 出力を抽出したい:

 R{abc}
 R{xyz}
 D{mnoR{xyz}}
 R{R{abc}aD{mnoR{xyz}}}

現在、 msdnに見られるように、バランスのとれたグループ アプローチを使用して、{} グループの内部にあるもののみを抽出できます。パターンは次のとおりです。

 ^[^{}]*(((?'Open'{)[^{}]*)+((?'Target-Open'})[^{}]*)+)*(?(Open)(?!))$

出力に R{} と D{} を含める方法を知っている人はいますか?

4

3 に答える 3

3

ここでは別のアプローチが必要だと思います。最初の大きなグループに一致するとR{R{abc}aD{mnoR{xyz}}}(タイポの可能性についての私のコメントを参照してください)、正規表現では個々のグループをキャプチャできないため、内部のサブグループを取得できませんR{ ... }

したがって、消費せずにキャプチャする何らかの方法が必要であり、それを行うための明白な方法は、前向きな先読みを使用することでした. そこから、フォーカスの新しい変更に適応するためにいくつかの変更はありますが、使用した式を配置できます。

(?=([A-Z](?:(?:(?'O'{)[^{}]*)+(?:(?'-O'})[^{}]*?)+)+(?(O)(?!))))

[また、'Open' の名前を 'O' に変更し、閉じブレースの名前付きキャプチャを削除して短くし、一致のノイズを回避しました]

regexhero.net (私がこれまでに知っている唯一の無料の .NET 正規表現テスター) で、次のキャプチャ グループを取得しました。

1: R{R{abc}aD{mnoR{xyz}}}
1: R{abc}
1: D{mnoR{xyz}}
1: R{xyz}

正規表現の内訳:

(?=                         # Opening positive lookahead
    ([A-Z]                  # Opening capture group and any uppercase letter (to match R & D)
        (?:                 # First non-capture group opening
            (?:             # Second non-capture group opening
                (?'O'{)     # Get the named opening brace
                [^{}]*      # Any non-brace
            )+              # Close of second non-capture group and repeat over as many times as necessary
            (?:             # Third non-capture group opening
                (?'-O'})    # Removal of named opening brace when encountered
                [^{}]*?     # Any other non-brace characters in case there are more nested braces
            )+              # Close of third non-capture group and repeat over as many times as necessary
        )+                  # Close of first non-capture group and repeat as many times as necessary for multiple side by side nested braces
        (?(O)(?!))          # Condition to prevent unbalanced braces
    )                       # Close capture group
)                           # Close positive lookahead

以下は C# では機能しません

再帰的な正規表現を使用するオプションがあったので、PCREエンジンでどのように機能するかを実際に試してみたかったのですが、私はそれに慣れていて、より短い正規表現が得られたので簡単だったと思います:)

(?=([A-Z]{(?:[^{}]|(?1))+}))

正規表現101のデモ

(?=                    # Opening positive lookahead
    ([A-Z]             # Opening capture group and any uppercase letter (to match R & D)
        {              # Opening brace
            (?:        # Opening non-capture group
                [^{}]  # Matches non braces
            |          # OR
                (?1)   # Recurse first capture group
            )+         # Close non-capture group and repeat as many times as necessary
        }              # Closing brace
    )                  # Close of capture group
)                      # Close of positive lookahead
于 2013-09-26T14:47:54.310 に答える
0

.Net 正規表現でグループのバランスをとると、何をキャプチャするかを正確に制御できます。.Net 正規表現エンジンは、グループのすべてのキャプチャの完全な履歴を保持します (各グループの最後の発生のみをキャプチャする他のほとんどのフレーバーとは異なります)。

MSDN の例は少し複雑すぎます。ネスト構造を一致させるためのより簡単なアプローチは次のとおりです。

(?>
    (?<O>)\p{Lu}\{   # Push to the O stack, and match an upper-case letter and {
    |                # OR
    \}(?<-O>)        # Match } and pop from the stack
    |                # OR
    \p{Ll}           # Match a lower-case letter
)+
(?(O)(?!))        # Make sure the stack is empty

または一行で:

(?>(?<O>)\p{Lu}\{|\}(?<-O>)|\p{Ll})+(?(O)(?!))

Regex Storm での作業例

あなたの例では、文字列の先頭にも一致し"tes"ますが、心配する必要はありません。

少し修正することで、 ...ペア間のオカレンスをキャプチャすることもできます。R{}

(?>(?<O>)\p{Lu}\{|\}(?<Target-O>)|\p{Ll})+(?(O)(?!))

それぞれMatchGroupcalled"Target"があり、そのようなGroupものにはCapturefor each オカレンスがあります。これらのキャプチャのみを気にします。

Regex Storm での作業例- [テーブル] タブをクリックし、次の 4 つのキャプチャを調べます。${Target}

以下も参照してください。

于 2014-04-28T19:47:38.143 に答える