7

.png や .css などの特定の拡張子で終わらない URL 文字列のみを選択する正規表現が必要です。

私は以下をテストしました:

1)これは否定的な後読みを使用しています:

(?<!\.png|\.css)$

https://regex101.com/r/tW4fO5/1

2) 否定的な先読みを使用するこの他のもの:

^(?!.*[.]png|.*[.]css$).*$

https://regex101.com/r/qZ7vA4/1

どちらも問題なく動作するようですが、#1 (否定後読み) は 436 ステップ (リンクを参照) で処理されると言われていますが、#2 (否定先読み) は 173 ステップで処理されると言われています。

だから私の質問は:それはどういう意味ですか?公演への影響はありますか?

そして最後に、2 つの正規表現は本当に機能的に同等なのでしょうか?

編集: ソリューションの概要

まとめとして、正規表現を介して除外される文字列末尾の完全なリストを考慮します (典型的なシナリオは、静的リソースが apache によって提供され、動的リソースが別のエンジンによって提供される Web サーバーのセットアップです - 私の場合: php-fpm)。

PCRE 正規表現では、次の 2 つのオプションが可能です。

1)否定後読み

$(?<!\.(?:ico|gif|jpg|png|css|rss|xml|htm|pdf|zip|txt|ttf)$|(?:js|gz)$|(?:html|woff)$)

https://regex101.com/r/eU9fI6/1

否定の後読みには固定幅のパターンが必要なので (つまり、異なる長さのパターンを混在させることはできません)、いくつかの OR 後読みを使用したことに注意してください。これにより、このオプションの記述が少し複雑になります。さらに、これは私の意見ではパフォーマンスを低下させます。

2)否定先読み

^(?!.*[.](?:js|ico|gif|jpg|png|css|rss|xml|htm|html|pdf|zip|gz|txt|ttf|woff)$).*$

https://regex101.com/r/dP7uD9/1

先読みは、後読みよりわずかに高速です。これは、100 万回の反復を行った場合のテスト結果です。

後読み時間= 18.469825983047 秒
先読み時間 = 14.316685199738 秒

可変長パターンの問題がなければ、よりコンパクトに見える後読みを選択します。どっちでもいいです。最後に、私は先読みに行きました:

<LocationMatch "^(?!.*[.](?:js|ico|gif|jpg|png|css|rss|xml|htm|html|pdf|zip|gz|txt|ttf|woff)$).*$">
    SetHandler "proxy:unix:/var/run/php5-fpm.sock|fcgi://www/srv/www/gioplet/web/public/index.php"
</LocationMatch>
4

2 に答える 2

4

公演への影響はありますか?

ほとんどの場合、正規表現が一致を見つけるために必要なステップが増えるほど、パフォーマンスが低下します。後で正規表現を使用するプラットフォームにも依存しますが (たとえば、regex101.com を使用して .NET で使用する正規表現をテストする場合、正規表現に一致する遅延ドットによる壊滅的なバックトラッキングが発生するという意味ではありません。長文)。

2 つの正規表現は本当に機能的に同等ですか?

いいえ、そうではありません。または(?<!\.png|\.css)$が前に付いていない行末を検索します。を含まない行または で終わらない行を検索ます。それらを「同等」にするには(つまり、で終わる行または行が一致しないことを確認したい場合)、使用します.png.css^(?!.*[.]png|.*[.]css$).*$ .png .css.png.css

^(?!.*[.](?:png|css)$).*$
         ^^^^^^^^^^^^

両方の後と否定先読みで$がチェックされていることを確認してください。png css

正規表現にはまだ違いがあります。最初の正規表現は行末のみに一致し、2 番目の正規表現は行全体に一致します。

後読みソリューションを高速化する方法はありますか?

パターン 1 の後読みは、文字列内の各位置でチェックされることに注意してください。パターン 2 の先読みは、文字列の先頭で一度だけチェックされます。そのため、いくつかの正規表現フレーバー (.NET など) でのみ使用できる RightToLeft 修飾子を使用できない場合など、1 つの条件下で固定先読みソリューションの方が高速になります。

後読みパターンは文字列/行の終わりに到達した後、1 回だけチェックされるため、後$(?<!\.(?:png|css)$)読みソリューションはパターン 1よりも高速です。それでも、先読みよりもコストがかかる後読みの実装のため、これにはもう少し多くの手順が必要です。

どのソリューションが最速かを実際に確認するには、環境でパフォーマンス テストをセットアップする必要があります。

于 2016-02-18T08:49:52.407 に答える