2

GIF ファイルのフレームを区切る次の行があります。

preg_match_all('/(?P<frame>\x00\x21\xF9\x04.(?P<delay>..).\x00\x2C.*?)(?=\x00\x21\xF9\x04)/s', $fileContents, $matches, PREG_SET_ORDER);

GIF ファイル形式に精通している場合は、これに大きな欠陥があることに気付くかもしれません。先読みはフレーム ヘッダーのみを対象としているため、最後のフレームが検出されません。

代わりに、正規表現を次のように変更すると'/(?P<frame>\x00\x21\xF9\x04.(?P<delay>..).\x00\x2C.*?)(?=\x00\x21\xF9\x04|\x3B$)/s\x3Bはファイル ターミネータ (その後にファイル/文字列の実際の末尾が続きます) であり、すべてが失敗し、一度も一致しません。

Kodosでこれテストしましたが、これはバイナリ データであるため、私ができる最善のことはプレーンテキストの等価物であり、期待どおりに機能しました。関数preg_match('/\x00\x3B$/', $fileContents) 正しく一致しており、16 進エディタでファイルを分析すると、ファイルが本来あるべきレイアウトになっていることが確認されます。

では、なぜ|\x3B$先読みに追加すると完全に失敗するのでしょうか?

注: はい、gif 画像を操作するためのライブラリがあります。この質問は純粋にプロセスに関するものであり、最終結果ではありません。

編集:パイプスペースが実際には問題ではない可能性があることに気づきました。\x00\x21\xF9\x04 正規表現は or のいずれか に一致します(ファイル全体で単独で何度も出現する\x3Bため、これは役に立ちません)。\x3Bパイプスペースの後の複数の文字で問題が発生するようです...一種の。どちらも正規表現全体が失敗する原因になります\x3B$\x00\x3Bただし、 $ を探すだけでは何があっても失敗します。これは、何よりも $ アンカーの問題のようですが、ここで厄介なのはそれだけではないようです。

一致が0件になる順列:

//Grouping within lookahead:
'/(?P<frame>\x00\x21\xF9\x04.(?P<delay>..).\x00\x2C.*?)(?=(\x00\x21\xF9\x04|\x3B$))/s'
//Moving lookahead within frame subpattern:
'/(?P<frame>\x00\x21\xF9\x04.(?P<delay>..).\x00\x2C.*?(?=\x00\x21\xF9\x04|\x3B$))/s'
//Both of the above:
'/(?P<frame>\x00\x21\xF9\x04.(?P<delay>..).\x00\x2C.*?(?=(\x00\x21\xF9\x04|\x3B$)))/s'
//Separating to two lookaheads:
'/(?P<frame>\x00\x21\xF9\x04.(?P<delay>..).\x00\x2C.*?)((?=\x00\x21\xF9\x04)|(?=\x3B$))/s'
//Just looking for the end anchor without \x3B:
'/(?P<frame>\x00\x21\xF9\x04.(?P<delay>..).\x00\x2C.*?)(?=\x00\x21\xF9\x04|$)/s'
//Just trying to find the end of the file:
'/(?P<frame>\x00\x21\xF9\x04.(?P<delay>..).\x00\x2C.*?)(?=$)/s'
'/(?P<frame>\x00\x21\xF9\x04.(?P<delay>..).\x00\x2C.*?)$/s'
//Trying to find \x00\x3B, the last two bytes:
'/(?P<frame>\x00\x21\xF9\x04.(?P<delay>..).\x00\x2C.*?)(?=\x00\x21\xF9\x04|\x00\x3B)/s'
//With some more grouping experiments:
'/(?P<frame>\x00\x21\xF9\x04.(?P<delay>..).\x00\x2C.*?)(?=(\x00\x21\xF9\x04|\x00\x3B))/s'
'/(?P<frame>\x00\x21\xF9\x04.(?P<delay>..).\x00\x2C.*?)(?=(\x00\x21\xF9\x04)|(\x00\x3B))/s'
//Moving file end outside of lookahead:
'/(?P<frame>\x00\x21\xF9\x04.(?P<delay>..).\x00\x2C.*?)((?=\x00\x21\xF9\x04)|$)/s'
'/(?P<frame>\x00\x21\xF9\x04.(?P<delay>..).\x00\x2C.*?)((?=\x00\x21\xF9\x04)|\x3B$)/s'
'/(?P<frame>\x00\x21\xF9\x04.(?P<delay>..).\x00\x2C.*?)((?=\x00\x21\xF9\x04)|\x00\x3B)/s'
//Moving file end before header:
'/(?P<frame>\x00\x21\xF9\x04.(?P<delay>..).\x00\x2C.*?)(?=$|\x00\x21\xF9\x04)/s'
'/(?P<frame>\x00\x21\xF9\x04.(?P<delay>..).\x00\x2C.*?)(?=\x3B$|\x00\x21\xF9\x04)/s'
'/(?P<frame>\x00\x21\xF9\x04.(?P<delay>..).\x00\x2C.*?)(?=\x00\x3B|\x00\x21\xF9\x04)/s'
'/(?P<frame>\x00\x21\xF9\x04.(?P<delay>..).\x00\x2C.*?)(?=($)|(\x00\x21\xF9\x04))/s'
'/(?P<frame>\x00\x21\xF9\x04.(?P<delay>..).\x00\x2C.*?)(?=(\x3B$)|(\x00\x21\xF9\x04))/s'
'/(?P<frame>\x00\x21\xF9\x04.(?P<delay>..).\x00\x2C.*?)(?=(\x00\x3B)|(\x00\x21\xF9\x04))/s'
4

1 に答える 1

0

おそらく、パイプで区切られた値を独自の括弧のペアでグループ化する必要があります。

(?=(a|b))
于 2012-06-29T04:43:03.190 に答える