欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

OpenResty中正則模式匹配的2種方法詳解

 更新時間:2018年04月21日 14:23:58   作者:南琴浪  
在 OpenResty 中,同時存在兩套正則表達式規(guī)范:Lua 語言的規(guī)范和 Nginx 的規(guī)范,下面這篇文章主要給大家介紹了關于OpenResty中正則模式匹配的2種方法,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下。

前言

本文介紹 OpenResty 的兩種正則模式匹配。

首先需要說明的是,OpenResty 套件中包含了兩種語法:一種是主要基于 FFI API 實現的 OpenResty 語法,一種是類原生 Lua 腳本語言的語法。

在本文所介紹的內容中,對應以上兩種語法的正則模式匹配分別是 ngx.re.find 和 string.find 。

這兩種規(guī)則起到完全相同的作用:在 subject string 中搜索指定的模式的串,若找到匹配值就返回它的開始位置和結束位置的位數,否則返回兩個 nil 空值。需要注意的是,當查找到模式時才會產生兩個值,當例如只有一個變量時只會產生開始位置位數或一個 nil 空值。

即使你對 Lua 比較熟悉,也已不再建議使用 string.find 等 Lua 的正則語法。一是因為由于實現不同,Lua 提供的正則表達式的性能相比 ngx.re.* 的表現要遜色不少,二是 Lua 的正則語法并不符合 POSIX 規(guī)范,而 ngx.re.* 則由標準 POSIX 規(guī)范進行實現,后者明顯更具備通用性和現在意義。

還有一個很重要的原因,相比 string.* 的每次都需重新編譯一遍,OpenResty 提供的 ngx.re.* 規(guī)范能夠在編譯完成后對 Pattern 進行緩存(使用 “o” 參數),并且也能通過 “j” 參數啟用 JIT 來進一步提升性能(需 pcre JIT 支持)。

string.find

雖說已經實在沒什么要用 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")

以上示例的作用就是包含有 “360” 的 UA 進行匹配,匹配命中時返回的值為 匹配串的開始位置和結束位置的位數(從左往右) 。舉個例子,使用 ngx.say 對輸出值進行顯示,先完成以下代碼:

-- 定義變量
var = string.find(ngx.var.http_user_agent, "360")

-- 輸出
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 測試響應:

# 發(fā)個請求,順便指定 UA 為 360
curl example.com -A "360"

# 返回響應會看到由 ngx.say echo 回來的字符串
# 這里匹配到的 "360" 字符串位于字首,位數是 1
var=1

ngx.re.find

ngx.re.find 規(guī)范的優(yōu)勢已經在上文介紹過了,這里介紹下它的基本語法(更多說明可以參看 官方文檔 ),以及要發(fā)揮它的優(yōu)勢(使用 “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.* 規(guī)范,并且要實現更高性能的話,需要滿足三個條件:編譯時使用 –with-pcre-jit 參數以啟用 pcre JIT 支持;編譯時需要 lua-resty-core 支持(直接使用 OpenResty 安裝即可);以及使用 Lua 代碼時,需要在 init_by_lua 段引入 require 'resty.core.regex' 語句(引入 lua-resty-core API 支持),并在構建代碼時將使用 "jo" 參數作為你的習慣,這兩個參數提供 pcre JIT 和 Pattern Cache 開關。正如上面 example 中所用的那樣。

同樣作為前面舉例的實現,Lua 代碼變成了這樣:

-- 定義變量
var = ngx.re.find(ngx.var.http_user_agent, "360", "jo")

-- 輸出
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

然后我就發(fā)現,這個匹配坑我了,我把這段代碼單獨拿出來時訪問 /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

測試結果卻表明我的寫法并沒有錯,根據 echo 的結果作出的判斷是, ^/admin/ 的確對 /admin/xxx 進行了唯一匹配。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關文章

  • Lua Table轉C# Dictionary的方法示例

    Lua Table轉C# Dictionary的方法示例

    這篇文章主要給大家介紹了關于Lua Table轉C# Dictionary的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。
    2018-03-03
  • Lua學習筆記之數據類型

    Lua學習筆記之數據類型

    這篇文章主要介紹了Lua學習筆記之數據類型,本文同時講解了開發(fā)環(huán)境的搭建,需要的朋友可以參考下
    2014-09-09
  • Lua面向對象編程之基礎結構table簡例

    Lua面向對象編程之基礎結構table簡例

    今天小編就為大家分享一篇關于Lua面向對象編程之基礎結構table簡例,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-10-10
  • Lua中的函數代碼實例

    Lua中的函數代碼實例

    這篇文章主要介紹了Lua中的函數代碼實例,本文著重講解函數的寫法以及一些小知識,需要的朋友可以參考下
    2015-04-04
  • 深入探究Lua中的解析表達式

    深入探究Lua中的解析表達式

    這篇文章主要介紹了深入探究Lua中的解析表達式,對于其語法部分的說明和示例都超詳細,極力推薦此文!需要的朋友可以參考下
    2015-07-07
  • 深入談談lua中神奇的table

    深入談談lua中神奇的table

    table 在lua中是一個非常常用的數據結構,可以用來存放各種類型的元素,下面這篇文章就來給大家介紹了關于lua中神奇的table的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面來一起看看吧
    2018-07-07
  • Lua中算術運算符的使用示例

    Lua中算術運算符的使用示例

    這篇文章主要介紹了Lua中算術運算符的使用示例,是Lua入門學習中的基礎知識,需要的朋友可以參考下
    2015-05-05
  • 使用Lua來擴展C++程序的方法

    使用Lua來擴展C++程序的方法

    這篇文章主要介紹了使用Lua來擴展C++程序的方法,盡管更多的時候人們或許會想用C++來擴展Lua...需要的朋友可以參考下
    2015-07-07
  • Lua中的面向對象編程詳解

    Lua中的面向對象編程詳解

    這篇文章主要介紹了Lua中的面向對象編程詳解,本文講解了Lua中的類、繼承、多重繼承等內容,需要的朋友可以參考下
    2014-09-09
  • Lua中實現面向對象的一種漂亮解決方案

    Lua中實現面向對象的一種漂亮解決方案

    這篇文章主要介紹了Lua中實現面向對象的一種漂亮解決方案,本文給出實現代碼、使用方法及代碼分析,需要的朋友可以參考下
    2015-01-01

最新評論