一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術(shù)及教程分享平臺(tái)!
分類導(dǎo)航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務(wù)器之家 - 腳本之家 - Lua - OpenResty中正則模式匹配的2種方法詳解

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

2020-05-08 10:47南琴浪 Lua

在 OpenResty 中,同時(shí)存在兩套正則表達(dá)式規(guī)范:Lua 語言的規(guī)范和 Nginx 的規(guī)范,下面這篇文章主要給大家介紹了關(guān)于OpenResty中正則模式匹配的2種方法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。

前言

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

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

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

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

即使你對 Lua 比較熟悉,也已不再建議使用 string.find 等 Lua 的正則語法。一是因?yàn)橛捎趯?shí)現(xiàn)不同,Lua 提供的正則表達(dá)式的性能相比 ngx.re.* 的表現(xiàn)要遜色不少,二是 Lua 的正則語法并不符合 POSIX 規(guī)范,而 ngx.re.* 則由標(biāo)準(zhǔn) POSIX 規(guī)范進(jìn)行實(shí)現(xiàn),后者明顯更具備通用性和現(xiàn)在意義。

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

string.find

雖說已經(jīng)實(shí)在沒什么要用 string.find 的必要(前浪死在沙灘上),不過我還是打算簡單介紹下,因?yàn)槲椰F(xiàn)在就是用的這個(gè)(原因我在后文會(huì)提到)。

?
1
2
3
4
5
6
7
8
-- 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 進(jìn)行匹配,匹配命中時(shí)返回的值為 匹配串的開始位置和結(jié)束位置的位數(shù)(從左往右) 。舉個(gè)例子,使用 ngx.say 對輸出值進(jìn)行顯示,先完成以下代碼:

?
1
2
3
4
5
-- 定義變量
var = string.find(ngx.var.http_user_agent, "360")
 
-- 輸出
ngx.say("var=" .. var)

把它放到 Nginx 網(wǎng)站的 /example 路徑下:

?
1
2
3
4
5
6
location = /example {
 access_by_lua_block {
 var = string.find(ngx.var.http_user_agent, "360")
 ngx.say("var=" .. var)
 }
}

然后使用 curl 測試響應(yīng):

?
1
2
3
4
5
6
# 發(fā)個(gè)請求,順便指定 UA 為 360
curl example.com -A "360"
 
# 返回響應(yīng)會(huì)看到由 ngx.say echo 回來的字符串
# 這里匹配到的 "360" 字符串位于字首,位數(shù)是 1
var=1

ngx.re.find

ngx.re.find 規(guī)范的優(yōu)勢已經(jīng)在上文介紹過了,這里介紹下它的基本語法(更多說明可以參看 官方文檔 ),以及要發(fā)揮它的優(yōu)勢(使用 “o” 參數(shù)緩存和使用 pcre JIT)的所需要求。

?
1
2
3
4
5
6
7
8
-- 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ī)范,并且要實(shí)現(xiàn)更高性能的話,需要滿足三個(gè)條件:編譯時(shí)使用 –with-pcre-jit 參數(shù)以啟用 pcre JIT 支持;編譯時(shí)需要 lua-resty-core 支持(直接使用 OpenResty 安裝即可);以及使用 Lua 代碼時(shí),需要在 init_by_lua 段引入 require 'resty.core.regex' 語句(引入 lua-resty-core API 支持),并在構(gòu)建代碼時(shí)將使用 "jo" 參數(shù)作為你的習(xí)慣,這兩個(gè)參數(shù)提供 pcre JIT 和 Pattern Cache 開關(guān)。正如上面 example 中所用的那樣。

同樣作為前面舉例的實(shí)現(xiàn),Lua 代碼變成了這樣:

?
1
2
3
4
5
-- 定義變量
var = ngx.re.find(ngx.var.http_user_agent, "360", "jo")
 
-- 輸出
ngx.say("var=" .. var)

我的坑

最后來解釋下我為什么還在用 string.find 語法。原因比較尷尬,不是我不想用,而是我不能用。我使用了以下代碼:

?
1
2
3
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ā)現(xiàn),這個(gè)匹配坑我了,我把這段代碼單獨(dú)拿出來時(shí)訪問 /admin/xxx 或 /tools/xxx 就會(huì)被拒,但是我一把它放進(jìn)代碼構(gòu)筑后就形同虛設(shè)。當(dāng)然我能肯定不是我其它代碼的問題,因?yàn)閾Q成 string.find 后就好了。

為了確認(rèn)是不是正則寫錯(cuò)的鍋,我也做過以下測試:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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

測試結(jié)果卻表明我的寫法并沒有錯(cuò),根據(jù) echo 的結(jié)果作出的判斷是, ^/admin/ 的確對 /admin/xxx 進(jìn)行了唯一匹配。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對服務(wù)器之家的支持。

原文鏈接:https://sometimesnaive.org/article/69

延伸 · 閱讀

精彩推薦
  • LuaLua簡介、編譯安裝教程及變量等語法介紹

    Lua簡介、編譯安裝教程及變量等語法介紹

    這篇文章主要介紹了Lua簡介、編譯安裝教程及變量等語法介紹,本文同時(shí)講解了lua注釋語法、Lua命令行方式等內(nèi)容,需要的朋友可以參考下 ...

    junjie3632020-04-14
  • LuaLua和C語言的交互詳解

    Lua和C語言的交互詳解

    這篇文章主要介紹了Lua和C語言的交互詳解,Lua和C語言通過棧完成交互,本文結(jié)合代碼實(shí)例詳細(xì)講解了交互的方法,需要的朋友可以參考下 ...

    果凍想3702020-04-14
  • LuaLua實(shí)現(xiàn)__add方法重載示例

    Lua實(shí)現(xiàn)__add方法重載示例

    這篇文章主要介紹了Lua實(shí)現(xiàn)__add方法重載示例,本文直接給出實(shí)現(xiàn)代碼,需要的朋友可以參考下 ...

    腳本之家7452020-04-24
  • LuaLua中table庫函數(shù)方法介紹

    Lua中table庫函數(shù)方法介紹

    這篇文章主要介紹了Lua中table庫函數(shù)方法介紹,本文講解了concat、insert、maxn、remove、sort、foreachi等方法,需要的朋友可以參考下 ...

    腳本之家2502020-04-17
  • LuaLua中計(jì)算、執(zhí)行字符串中Lua代碼的方法

    Lua中計(jì)算、執(zhí)行字符串中Lua代碼的方法

    這篇文章主要介紹了Lua中計(jì)算、執(zhí)行字符串中Lua代碼的方法,類似JavaScript中eval函數(shù)的功能,在Lua中也可以實(shí)現(xiàn),需要的朋友可以參考下 ...

    腳本之家6322020-04-30
  • LuaLua中的元方法__newindex詳解

    Lua中的元方法__newindex詳解

    這篇文章主要介紹了Lua中的元方法__newindex詳解,本文講解了查詢與更新、監(jiān)控賦值、通過table給另一個(gè)table賦值等內(nèi)容,需要的朋友可以參考下 ...

    笨木頭8872020-04-09
  • LuaLua教程(二):基礎(chǔ)知識(shí)、類型與值介紹

    Lua教程(二):基礎(chǔ)知識(shí)、類型與值介紹

    這篇文章主要介紹了Lua教程(二):基礎(chǔ)知識(shí)、類型與值介紹,本文講解了Hello World程序、代碼規(guī)范、全局變量、類型與值等內(nèi)容,需要的朋友可以參考下 ...

    腳本之家5922020-04-28
  • Lua深入探究Lua中的解析表達(dá)式

    深入探究Lua中的解析表達(dá)式

    這篇文章主要介紹了深入探究Lua中的解析表達(dá)式,對于其語法部分的說明和示例都超詳細(xì),極力推薦此文!需要的朋友可以參考下 ...

    腳本之家3542020-05-05
主站蜘蛛池模板: 欧美日韩成人在线视频 | 欧美军人男同69gay | 免费人成黄页在线观看69 | 免费网址视频在线看 | 青草免费在线 | 四虎免费在线观看视频 | 人人艹在线视频 | 欧美人禽杂交在线视频 | 亚洲精品第一国产综合 | 99久久这里只有精品 | 国产精品视频一区二区三区w | 久久精品视频免费 | 久久人妻少妇嫩草AV無碼 | 国产精品视频一区二区三区经 | 亚洲国产成人久久77 | 国产精品九九久久一区hh | 16男男gaygays | 丝瓜视频看污片 | 日本xxxxx高清免费观看 | 娜娜啪| 免费标准高清看机机桶机机 | 美女禁区视频免费观看精选 | 午夜网| 日本高清在线看 | 欧美日韩导航 | 精品欧美男同同性videos | 美女撒尿毛片免费看 | 亚洲国产视频一区 | 肉车各种play文r | 精品国产日韩亚洲一区在线 | 亚洲成人在线播放 | 亚洲第一区在线观看 | 肉文高h文 | 91porny丨首页 | 人人人人看人人人做人人 | 艹b视频在线观看 | 国产在线麻豆波多野结衣 | 免费一级毛片完整版在线看 | 成年人在线免费观看视频网站 | 性xxx欧美 | 国内精品久久久久影院男同志 |