ngx_lua_API 指令詳解(二)ngx.re.match/find/gmatch/sub/gsub指令集合


1、先來個官方的ngx.re.match

location /ngx_re_match {
  default_type text/html;
  content_by_lua_block {
      local m, err = ngx.re.match("/live/4001493201083.m3u8", "[0-9]+")
       if m then
           -- m[0] == "4001493201083"
           ngx.say("makcj::",m[0])
       else
           if err then
               ngx.log(ngx.ERR, "error: ", err)
               return
           end
           ngx.say("match not found")
       end
  }
}

分享:以上可以匹配nginx的uri里面的變量很方便。

2、ngx.re.match 指令

語法: captures,err = ngx.re.match(subject,regex,options?ctx?res_table?)

上下文: 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 *

subject使用regex可選的Perl兼容正則表達式匹配字符串options。

只有匹配的第一次出現被返回,或者nil如果沒有匹配。在出現錯誤的情況下,如看到錯誤的正則表達式或超過PCRE堆棧限制,nil並返回描述錯誤的字符串。

當發現匹配時,captures返回一個Lua表,其中captures[0]保持整個子串匹配,並captures[1]保存第一個括號子模式的捕獲,captures[2]第二個等等。

#demo1

local m, err = ngx.re.match("Tinywan, 1234", "([0-9])[0-9]+")
ngx.say("match_value  m[0]:",m[0])
ngx.say("match_value  m[1]:",m[1])

輸出:

match_value  m[0]:1234
match_value  m[1]:1

說明:很簡單的,不必解釋

#demo2

local m, err = ngx.re.match("hello, 1234", "([0-9])(?<remaining>[0-9]+)")
ngx.say("match_value  m[0]:",m[0])
ngx.say("match_value  m[1]:",m[1])
ngx.say("match_value  m[2]:",m[2])
ngx.say("match_value  m['remaining']:",m["remaining"])

輸出

match_value  m[0]:1234
match_value  m[1]:1
match_value  m[2]:234
match_value  m['remaining']:234

說明:命名捕獲,並在與編號捕獲的鍵值對相同​​的Lua表中返回

 

3、ngx.re.find

語法: from,to,err = ngx.re.find(subject,regex,options?ctx?,nth?)

上下文: 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 *

該方法與ngx.re.match方法基本類似,不同的地方在於ngx.re.find返回的是匹配的字串的起始位置索引和結束位置索引,如果沒有匹配成功,那么將會返回兩個nil,如果匹配出錯,還會返回錯誤信息到err中。

#demo1

local s = "hello Tinywan, 123456"
local from, to, err = ngx.re.find(s, "([0-9]+)", "jo")
if from then
    ngx.say("from: ", from)
    ngx.say("to: ", to)
    ngx.say("matched: ", string.sub(s, from, to))
else
    if err then
        ngx.say("error: ", err)
        return
    end
    ngx.say("not matched!")
end

輸出:

from: 16
to: 21
matched: 123456

說明:字符串s的長度為21個字節,from:表示匹配成功的索引開始位置,to:則為結束位置,而配置的字符串長度為:to-from+1

!!!官方推薦理由:因為這個API函數不會創建新的Lua字符串或新的Lua表,它比ngx.re.match快得多。應盡可能使用。

  自0.9.3發布以來,支持可選的第五個參數,nth以指定要返回哪個(子匹配)捕獲的索引。當nth為0(默認為)時,返回整個匹配子字符串的索引; 何時nth為1,則返回第一個配對捕獲的索引; 當nth為2時,則返回第二次匹配捕獲,依此類推。當指定的子配對不匹配時,nil將返回兩個值

local str = "hello Openresty, 1234878787"
local from, to = ngx.re.find(str, "([0-9])([0-9]+)", "jo", nil, 2)
if from then
    ngx.say("matched 2nd submatch: ", string.sub(str, from, to))  
end

輸出:matched 2nd submatch: 234878787

4、ngx.re.gmatch

語法: iterator,err = ngx.re.gmatch(subject,regex,options?)

上下文: 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 *

與ngx.re.match類似,但是返回一個Lua迭代器,以便讓用戶程序員<subject>使用PCRE 對string參數的所有匹配進行迭代regex。如果出現錯誤,就像看到形式不正常的正則表達式,nil並且將返回描述錯誤的字符串

#demo1

local iterator, err = ngx.re.gmatch("hello, world!", "([a-z]+)", "i")
if not iterator then
    ngx.log(ngx.ERR, "error: ", err)
    return
end
local m
m, err = iterator()    -- m[0] == m[1] == "hello"
ngx.say(" 1 m[0] == ",m[0]," m[1] == ",m[1])
if err then
    ngx.log(ngx.ERR, "error: ", err)
    return
end
m, err = iterator()    -- m[0] == m[1] == "world"
ngx.say(" 2 m[0] == ",m[0]," m[1] == ",m[1])
if err then
    ngx.log(ngx.ERR, "error: ", err)
    return
end
m, err = iterator()    -- m == nil
if err then
    ngx.log(ngx.ERR, "error: ", err)
    return
end

輸出:

 1 m[0] == hello m[1] == hello
 2 m[0] == world m[1] == world

#demo2

local it, err = ngx.re.gmatch("hello, world!", "([a-z]+)", "i")
if not it then
    ngx.log(ngx.ERR, "error: ", err)
    return
end
while true do
    local m, err = it()
    if err then
        ngx.log(ngx.ERR, "error: ", err)
        return
    end
    if not m then
        -- no match found (any more)
        break
    end
    -- found a match
    ngx.say(m[0])
    ngx.say(m[1])
end

輸出:

hello
hello
world
world

可選options參數與ngx.re.match方法完全相同的語義。

當前的實現需要僅在單個請求中使用返回的迭代器。也就是說,不應該將它分配給屬於持久命名空間的變量,如Lua包。

該方法需要在Nginx中啟用PCRE庫。

 

5、ngx.re.sub

語法: newstr,n,err = ngx.re.sub(subject,regex,replace,options?)

上下文: 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 *

將帶有字符串或函數參數regex的subject參數字符串的Perl兼容正則表達式的第一個匹配替換replace。可選options參數與ngx.re.match具有完全相同的含義。

此方法返回所生成的新字符串以及成功替換的數量。在出現故障的情況下,如正則表達式或<replace>字符串參數中的語法錯誤,它將返回nil一個描述該錯誤的字符串。

當replace是字符串時,它被視為用於字符串替換的特殊模板

#demo1

local newstr, n, err = ngx.re.sub("hello, 1234", "([0-9])[0-9]", "[$0][$1]")
if newstr then
    -- newstr == "hello, [12][1]34"
    -- n == 1
    ngx.say("newstr == ",newstr)
else
    ngx.log(ngx.ERR, "error: ", err)
    return
end

輸出:

newstr == hello, [12][1]34
n == 1

說明:其中$0引用由模式匹配的整個子字符串,並$1引用第一個括號化的捕獲子字符串

6、ngx.re.gsub

語法: newstr,n,err = ngx.re.gsub(subject,regex,replace,options?)

上下文: 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 *

就像ngx.re.sub一樣,但是全局替換

#demo1

local newstr, n, err = ngx.re.gsub("hello, world", "([a-z])[a-z]+", "[$0,$1]", "i")
if newstr then
   ngx.say("newstr == ",newstr)
   ngx.say("n == ",n)
else
    ngx.log(ngx.ERR, "error: ", err)
    return

輸出:

newstr == [hello,h], [world,w]
n == 2

說明:該方法需要在Nginx中啟用PCRE庫

#demo2

local func = function (m)
    return "[" .. m[0] .. "," .. m[1] .. "]"
end
local newstr, n, err = ngx.re.gsub("hello, world", "([a-z])[a-z]+", func, "i")
ngx.say("newstr == ",newstr)
ngx.say("n == ",n)

輸出:

newstr == [hello,h], [world,w]
n == 2

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM