OpenRestyの2つの正規パターンマッチの方法を解説
プリアンブル
この記事では、OpenRestyの2種類の正規パターンマッチを紹介します。
まず最初に、OpenRestyスイートには、主にFFI APIの実装に基づいたOpenRestyの構文と、ネイティブのLua系スクリプト言語用の構文の2つがあることに注意する必要があります。
この記事では、この2つの構文の正規のパターン・マッチングを、それぞれngx.re.findとstring.findとします。
この2つのルールは全く同じ目的を果たします。指定されたパターンの文字列をサブジェクトの文字列から探し、マッチした場合は開始と終了の数字を返し、そうでない場合はnil null値2つを返します。2つの値は、パターンが見つかった場合にのみ生成されることに注意してください。例えば、変数が1つしかない場合は、開始位置の数字またはnil null値のみが生成されます。
Luaに慣れていても、string.findのようなLuaの正規構文を使うことは、もはや推奨されません。これは、Luaの正規表現は実装の違いからngx.re.*に比べて性能がかなり劣ること、また、Luaの正規構文はPOSIXに準拠していないのに対し、ngx.re.*は標準POSIX仕様で実装されていて、一般性や今日的な関連性がかなり高いためです。
もう一つの重要な理由は、毎回再コンパイルが必要なstring.*に対して、OpenRestyが提供するngx.re.*仕様はコンパイル後にPatternをキャッシュできること("o"パラメータを使用)と、さらにパフォーマンス向上のために"j "パラメータでJITを有効にできる(pcre JITサポート必要)ことです。
文字列検索
本当はもうstring.findを使う必要はないのですが(前波はビーチで死んだ)、今使っているのがこれなので簡単に紹介します(理由は後述)。
-- syntax
from, to, err = string.find(s, pattern, start, [plain])
-- context
init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_ lua*, ngx.timer.\*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
-- example
string.find(ngx.var.http_user_agent, "360")
上記の例は、UAに"360"が含まれる場合にマッチし、マッチがヒットしたときに返される値が、文字列の先頭と末尾のビット数(左から右へ)であるという仕組みになっています。例として、ngx.sayを使って出力を表示するには、まず以下のコードを完成させます。
-- Define the variables
var = string.find(ngx.var.http_user_agent, "360")
-- output
ngx.say("var=" . var)
Nginx サイトの /example パスの下に置いてください。
location = /example {
access_by_lua_block {
var = string.find(ngx.var.http_user_agent, "360")
ngx.say("var=" . var)
}
}
次に、curl を使用してレスポンスをテストします。
# Send a request, specifying the UA as 360 by the way
curl example.com -A "360"
# Return the response with the string echoed by ngx.say
# The "360" string matched here is at the beginning of the word and has 1 digit
var=1
ngx.re.find
ngx.re.find仕様の利点はすでに上で説明したとおりですので、ここでは基本的な構文を説明します(詳しくは 公式ドキュメント ) と、それを利用するための要件 ("o" パラメータ キャッシュの使用と pcre JIT の使用) を説明します。
-- syntax
from, to, err = ngx.re.find(subject, regex, options?, ctx?, nth?)
-- context
init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_ lua*, ngx.timer.\*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
-- example
ngx.re.find(ngx.var.http_user_agent, "360", "jo")
ngx.re.*の仕様を使い、より高いパフォーマンスを得るためには、次の3つの条件を満たす必要があります。 -with-pcre-jit 引数でコンパイルして pcre JITサポートを有効にし、 lua-resty-core サポート (OpenResty で直接インストール)、Luaコードを使う場合は require 'resty.XXX' を導入し、'resty.XXX' を使用する必要があります。 init_by_luaセクションにrequire 'core.regex' ステートメントを導入し(lua-resty-core APIサポートを導入するため)、コードを構築する際に"jo"パラメータを使用する習慣をつけてください、これらは両方ともpcre JITとパターンキャッシュのスイッチを提供するものです。上記の例で使用されているように
また、先ほどの例の実装として、Luaのコードは以下のようになります。
-- Define variables
var = ngx.re.find(ngx.var.http_user_agent, "360", "jo")
-- Output
ngx.say("var=" . var)
マイピット
最後に、なぜ私がいまだにstring.find構文を使っているのかを説明します。理由はかなり恥ずかしく、使いたくないわけではないのですが、使えないのです。私は次のようなコードを使っています。
if (ngx.re.find(ngx.var.request_uri, "^/admin/", "jo") ~= nil or ngx.re.find(ngx.var.request_uri, "^/tools/" , "jo") ~= nil) then
return ngx.exit(ngx.HTTP_CLOSE)
end
その時、マッチングがうまくいっていないことに気がつきました。コードを単体で取り出すと、/admin/xxxや/tools/xxxにアクセスしても拒否されるのに、コードビルドに入れた途端、うまくいかなくなったのです。string.findに切り替えた後は大丈夫なので、私のコードの他の部分が原因ではないことは確かです。
間違ったルールのせいでないことを確認するために、次のようなテストも行いました。
if (ngx.var.request_uri == "/test1/") then
if (ngx.re.find("/admin/test/", "^/admin/", "jo") ~= nil) then
ngx.say("1=" . ngx.re.find("/admin/test/", "^/admin/", "jo"))
end
elseif (ngx.var.request_uri == "/test2/") then
if (ngx.re.find("/admintest/", "^/admin/", "jo") ~= nil) then
ngx.say("2=" . ngx.re.find("/admintest/", "^/admin/", "jo"))
end
elseif (ngx.var.request_uri == "/test3/") then
if (ngx.re.find("/artic/", "^/admin/", "jo") ~= nil) then
ngx.say("3=" . ngx.re.find("/artic/", "^/admin/", "jo"))
end
elseif (ngx.var.request_uri == "/test4/") then
if (ngx.re.find("/artic", "^/admin/", "jo") ~= nil) then
ngx.say("4=" . ngx.re.find("/artic", "^/admin/", "jo"))
end
elseif (ngx.var.request_uri == "/test5/") then
if (ngx.re.find("/offline/admin/", "^/admin/", "jo") ~= nil) then
ngx.say("5=" . ngx.re.find("/offline/admin/", "^/admin/", "jo"))
end
elseif (ngx.var.request_uri == "/test6/") then
if (ngx.re.find("/offline/", "^/admin/", "jo") ~= nil) then
ngx.say("6=" . ngx.re.find("/offline/", "^/admin/", "jo"))
end
elseif (ngx.var.request_uri == "/test7/") then
if (ngx.re.find("/admin/", "^/admin/", "jo") ~= nil) then
ngx.say("7=" . ngx.re.find("/admin/", "^/admin/", "jo"))
end
elseif (ngx.var.request_uri == "/test8/") then
if (ngx.re.find("/adm/in", "^/admin/", "jo") ~= nil) then
ngx.say("8=" . ngx.re.find("/adm/in", "^/admin/", "jo"))
end
else
if (ngx.var.request_uri == "/test9/") then
if (ngx.re.find("/admin", "^/admin/", "jo") ~= nil) then
ngx.say("9=" . ngx.re.find("/admin", "^/admin/", "jo"))
end
end
end
テストの結果、間違いはなく、エコーの結果、^/admin/ が /admin/xxx に一意に一致することがわかりました。
要約すると
上記はこの記事のすべての内容です、私はあなたの勉強や仕事のためのこの記事の内容は、特定の参照学習価値があることを願って、あなたが交換するメッセージを残すことができます質問がある場合は、BinaryDevelopのあなたのサポートに感謝します。
関連
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Luaオブジェクト指向プログラミング。基本構造表の簡単な例
-
Lua Observerパターンの解析 イベント配信システム構築のためのベストプラクティス
-
Luaのプログラミング例(4)。テーブルライブラリ、文字列ライブラリ、システムライブラリからなるLua標準ライブラリ
-
Luaにおける関数の基本的な使い方をご紹介します。
-
Luaプログラミングにおける例外処理の解析
-
Luaにおける配列の概念の説明
-
Luaにおけるbreak文の使い方を解説します
-
Luaで関係演算子を使用するためのチュートリアル
-
Luaは配列(tabble)に値が含まれているかどうかを検出します。
-
Lua: メソッド 'xxxx' (nil値) を呼び出そうとしました。