1

「単一行」オプションがオンになっていると、否定的な先読みを伴う正規表現が失敗する理由を理解しようとしています。

例 (簡略化):

<source>Test 1</source>
<source>Test 2</source>
<target>Result 2</target>
<source>Test 3</source>

これ:

<source>(?!.*<source>)(.*?)</source>(?!\s*<target)

シングルラインオプションがオンの場合は失敗し、シングルラインオプションがオフの場合は機能します。たとえば、これは機能します(単一行オプションを無効にします):

(?-s:<source>(?!.*<source>)(.*?)</source>(?!\s*<target))

私の理解では、単一行モードでは単にドット「。」が許可されます。改行に一致させるために、なぜそれが上記の式に影響を与えるのかわかりません.

ここで私が見逃していることを誰かが説明できますか?

::::::::::::::::::::::

編集: (?!.*) は、キャプチャ グループではなく、 否定的な先読みです。

 <source>(?!.*?<source>)(.*?)</source>(?!\s*<target)

単一行モードがオンの場合も失敗するため、これは貪欲の問題ではないようです。Regex デザイナー (Expresso や Rad regex など) で試してください。

単一行をオフにすると、一致します(予想どおり):

<source>Test 1</source>    
<source>Test 3</source>

1 回線 ON の場合:

<source>Test 3</source>

最初のものにも一致しない理由がわかりません。最初の否定的な先読みが含まれていないため、式と一致するはずです。

4

2 に答える 2

2

それが「失敗」する理由は、あなたがネガティブな先読みを置き忘れたように見えるからです。

<source>(?!.*<source>)(.*?)</source>(?!\s*<target)
        ^^^^^^^^^^^^^^

ここで、ここで何が行われるかを考えてみましょう。これは、その位置からの一致(?!.*<source>)ないことを示す先読みです。.*<source>

まあ、単一行モードでは、すべてに.一致します。最初の2つを一致させた後、実際<source>あります!したがって、最初の2つは負の先読みが失敗します。.*<source><source>

最後<source>に、.*<source>一致しなくなったため、ネガティブ先読みが成功します。パターンの残りの部分も成功します。そのため<source>Test 3</source>、単一行モードでしか取得できません。

于 2010-06-01T09:58:34.153 に答える
2

これがあなたが探しているものだと思います:

<source>((?:(?!</?source>).)*)</source>(?!\s*<target)

アイデアは、各文字を一度に 1 つずつ一致させるというものですが、それが</source>. また、/?先読みに を追加すると、貪欲でない量指定子を使用する必要がなくなります。

于 2010-06-01T12:46:20.080 に答える