空のバックレファレンスは、PHPの一致障害を引き起こします…回避策はありますか?

StackOverflow https://stackoverflow.com/questions/3459095

  •  27-09-2019
  •  | 
  •  

質問

潜在的に空の逆を使用するPHPでの正規表現に問題があります。私はそれが説明されているように機能することを望んでいました http://www. Regual-Expressions.info/brackets.html:

特定の一致の試行で背面が使用されなかった場合(質問マークが最初の背景をオプションにした最初の例など)、それは単に空です。正規表現で空の逆を使用することはまったく問題ありません。それは単に無に置き換えられます。

しかし、PHPは少し違っているようです... http://php.net/manual/en/regexp.reference.back-references.php:

Subpatternが実際に特定の一致で使用されていない場合、それへのバック参照は常に失敗します。

単純化された例として、私は次の2つのことをこのregexと一致させたいと思います。

  • {何か} ... {/何か}
  • {何か:else} ... {/何か:else}

「何か」が事前に知られており、「他の」は何でも(または何もない)ことができます。

それで、私は次の正規表現を試しました(「他の」シンプルさのためにハードコードされた "else):

preg_match("/\{(something(:else)?)\}(.*?)\{\/something\\2\}/is", $data, $matches)

残念ながら(:else)?一致しません、 2の背景は失敗します。 2をオプション( 2?)にすると、{何か} ... {何か:else}を一致させるかもしれません。

私は正規表現の制限に遭遇しましたか(悪名高い「あなたはregexではなくパーサーが必要です」)、またはこれは修正可能ですか?

テストプログラム:

<?php
    $data = "{something} ... {/something}
             {something:else} ... {/something:else}
             {something:else} ... {/something}";

    // won't match {something} ... {/something}
    preg_match_all("/\{(something(:else)?)\}(.*?)\{\/something\\2\}/is", $data, $matches);
    print_r($matches);

    // change \\2 to \\2? and it matches too much
    preg_match_all("/\{(something(:else)?)\}(.*?)\{\/something\\2?\}/is", $data, $matches);
    print_r($matches);
?>
役に立ちましたか?

解決

2の代わりに 1を単に使用してみませんか?

preg_match_all("/\{(something(:else)?)\}(.*?)\{\/\\1\}/is", $data, $matches);

「パーサーが必要」の問題については、ネストされた構造を解析するためにそれを必要とします。

他のヒント

さて、なぜ置き換えてみませんか?または?

変化する

"/\{(something(:else)?)\}(.*?)\{\/something\\2\}/is"

"/\{(something(:else|))\}(.*?)\{\/something\\2\}/is"

そうすれば、参照は常にキャプチャされますが、時々空になります(大丈夫です)...

そのような場合のクラスに続くクラス({何か} ... {/何か}または{何か}などのように)preg_contentfinder クラス

https://gist.github.com/sl5net/7029093#file-sl5_preg_contentfinder-php

        $content1 = $content = '`ha <!--[01.o0]-->1<!--[/01.o0]-->

こんにちは[02.o0] 2 ho 3 `';

            $pos_of_next_search = 0;
        $begin = '(<!--)?\[([^\]>]*\.o0)\](-->)?';
        $end = '<!--\[\/($2)\]-->';
        $cf = new SL5_preg_contentFinder($content);
        $cf->setBeginEnd_RegEx($begin, $end);
        $cf->setSearchMode('use_BackReference_IfExists_()$1${1}');
        $loopCount = 0;
        while ($loopCount++ < 5) {
            $cf->setPosOfNextSearch($pos_of_next_search);
            list($findPos['begin_begin'], $findPos['end_begin'],
                $findPos['begin_end'], $findPos['end_next'], $matchesReturn) = $cf->get_borders_left(__LINE__);
            $content = $cf->getContent();
            $expectedContent = $maxLoopCount;
            if ($maxLoopCount>3)$expectedContent = '';
            if ($content != $expectedContent)
                die(__LINE__ . 'ERROR :   $content != $expectedContent :' . " '$content'!= '$expectedContent ");
            if (is_null($findPos['begin_begin'])) {
                break;
            }
            echo(__LINE__ . ': '.$content1.' ==> "' . $content . '"');

            $pos_of_next_search = $findPos['end_next'];
        }
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top