1

次のテキストの「ダイニング:」に続く数字を解析しようとしています。したがって、「666」が返されます。

    MAIN LEVEL
        Entrance: 11
        Dining: 33

    SECOND LEVEL
        Entrance: 4444
        Living: 5555
        Dining: 666

    THIRD LEVEL
        Dining: 999
        Kitchen: 000
        Family: 33332

次のようなものを使用すると(?:\bDining:\s)(.*\b)、MAIN の下で最初に発生したものがキャプチャされます。したがって、正規表現で指定しようとしてSECOND LEVELおり、その後に、改行、複数のスペース、および任意のテキストの繰り返しパターンが続きますDining:このデモは、私が遭遇した 2 つの問題を示しています。使用される正規表現は次のとおりです。(?:\bSECOND\sLEVEL(\n\s+.*)*Dining:)(.*\b)

  1. を含む最後の行を削除するまで、 「壊滅的なバックトラッキング」エラーが表示されますLaundry: 1。これは、マッチ数が多すぎることが原因ですか?
  2. その行を削除すると、正規表現は .. の下の最後の一致のみをキャプチャし、 の下OTHER LEVELの一致ではなく '2' を返しますSECOND LEVEL

Dining:下に存在しない場合があるSECOND LEVELため、何も返されません。

SECOND LEVELの番号のみをキャプチャし、Dining:存在しない場合は何も返さない正規表現は何ですか? ストレートアップの正規表現が推奨され、可能であれば Java でのループはありません。ありがとう

4

2 に答える 2

2

否定先読みベースの正規表現を使用します。

"(?m)^\\s*\\bSECOND LEVEL\\n(?:(?!\\n\\n)[\\s\\S])*\\bDining:\\s*(\\d+)"

デモ

于 2015-12-27T00:55:35.677 に答える
1

ここからの壊滅的なバックトラッキングについて私が知っている最良の例は(x+x+)+y. つまり、x を含むキャプチャ グループを分割する方法が多すぎるため、正しい境界を見つけることができません。

xxxxy は、最初の 2 回 + 1 回、3 回目の 2 回、または最初の 2 回と 3 回目のそれぞれの 1 回、または最初の 3 回ともう 1 回と最後の 1 回のいずれかです。ご覧のとおり危険です!

前のと組み合わせてで囲むと、 theが悪夢になる可能性があることに(?:\bSECOND\sLEVEL(\n\s+.*)*Dining:)(.*\b)注意してください。これを書き直す必要があります。これにより、各量指定子が次の開始前に終了し、バックトラックが最小限に抑えられます。(\n\s+.*)*.*\n\s*(\n\s+[^\s\n][^\n]*)*

この種の考え方を念頭に置いて、文字列に一致する次の正規表現を思いつきました。

(?<=SECOND LEVEL\n)(?:\s+(?:[^\s\n:][^\n:]*):[^\n]*)*\s+Dining:\s*([^\s\n][^\n$]*)
于 2015-12-27T01:13:18.110 に答える