LUA 正則表達式 - 模式匹配


 

模式匹配相關庫函數

 

按匹配查找:string.find (s,pattern [,init [,plain]])

兩個返回值,被捕獲內容的起始位置和終止位置,如未找到則返回nil。

參數s:指定字符串,參數pattern:匹配,可選參數init:初始查找位置(如果是負數將從字符串尾開始定位),可選參數plain:無參數時按匹配查找,當參數為true時使用單純字符串進行匹配。

 

按位置捕獲:string.sub (s,i [,j])

返回以i,j定位的子串內容。

參數s:指定字符串,參數i:初始查找位置(如果是負數將從字符串尾開始定位),可選參數j:無參數時等價j為最大值,如果j比整個字符串大則自動修正,如果j比i小則返回空字符串。

 

按匹配捕獲:string.match (s,pattern [,init])

返回按匹配捕獲的子串,如未捕獲則返回nil。如果在參數pattern中使用()進行捕獲則返回值變為捕獲到內容。

參數s:指定字符串,參數pattern:匹配,可選參數init:初始查找位置(如果是負數將從字符串尾開始定位)

 

按匹配捕獲並替換:string.gsub (s,pattern,replace [,n])

兩個返回值,成功替換后的新字符串和被替換的次數,如未找到匹配則返回s原始內容。

參數s:指定字符串,參數pattern:匹配,參數replace:替換內容(可以是表或函數),可選參數n:替換次數,無參數則全部替換。

 

迭代器函數:string.gmatch (s,pattern)

每次迭代返回一個匹配的子串內容,該函數用於逐一遍歷字符串中所有捕獲到的匹配。

參數s:指定字符串,參數pattern:匹配

 

模式匹配預置的字符分類

 .  -- 任意字符
%a  -- 字母
%c  -- 控制符,如\n
%d  -- 數字
%g  -- 除空格外的可打印字符
%l  -- 小寫字母
%p  -- 標點符號
%s  -- 空白字符
%u  -- 大寫字母
%w  -- 字母和數字
%x  -- 十六進制數字
%n  -- 第n次被()捕獲的內容,n是一個數字,如:%1 %2 %3,而%0則意味着整個匹配而不是捕獲
%f  -- 前置排除模式
%b  -- 范圍匹配,使用兩個字符參數確定前后成對的區域,如:%b<> %b{} %b33 %b-+ 遵循最遠距離貪婪匹配規則

 

魔法字符(修飾符)

 %  -- 轉義符
 +  -- 重復一次或多次
 *  -- 重復零次或多次(最遠距離貪婪匹配)
 -  -- 重復零次或多次(最近距離匹配)
 ?  -- 重復零次或一次(表示可有可無)
 ^  -- 錨定開頭
 $  -- 錨定結尾
[]  -- 自定義字符分類,分類間的關系是"或"
()  -- 捕獲,空的捕獲可以返回位置信息,如:字符串"Name",模式"()am()"返回2,4。
   使用修飾符時一定要注意上下文,如:.*很可能匹配超預期
   在結尾使用"-"並沒有意義,這樣只能匹配到空字符,-后面總是要跟上一些東西來限制擴展范圍

 

當模式匹配字母大寫時表示其補集,非字母代表其本身,在模式中%需要轉義,如%%。而匹配無意義的修飾符時也需要加轉義字符%。

前置排除模式:簡單來說%f[char-set]是判斷[char-set]后面緊跟的字符是否屬於[char-set]而[char-set]之前的字符不屬於[char-set],例如:"%f[%a]abc123"對於字符串"Hi+abc123"來說,字符a屬於[%a]而前面的+不屬於[%a]即模式成立。

()捕獲與%n配合可以對[]自定義字符分類中不確定的內容在后續進行進一步的確認。

例如:

s = [[then he said: "it's all right"!]]
print (string.match (s, "(["'])(.-)%1")
-->" it's all right 輸出了兩個參數,分別是"和it's all right。
以"或'開頭,零個或多個任意字符序列,遇到第一次捕獲到的匹配為結尾,使得不確定的字符分類在最后得到了確定的匹配
類似的例子如:長字符串或長注釋[==[ ]==]中不確定的=數量

 

翻譯一些例子

"[_%a][_%w]*"  -- [下划線任意字母][零個或多個下划線任意字母或數字]*,匹配LUA中合法的標識符

"[+-]?%d+"     -- [可有可無的正號負號]?任意數字序列+,匹配123,-21,+456

"^%d"          -- 任意數字開頭^,匹配整段字符串第一個字符是數字

"^[+-]?%d+$"   -- 開頭^[可有可無正號負號]?任意數字序列結尾$,匹配純整型數值

"%[(=*)%[(.-)%]%1%]"  -- 轉義[捕獲1(零個或多個等號)轉義[捕獲2(零個或多個任意字符)轉義]捕獲1的內容%1轉義],匹配LUA長字符串樣式[==[]==]

 

替換

string.gsub的第三個參數不僅可以是字符串,還可以是函數或者表。

string.gsub配合%n替換

例如:

print (string.gsub ("Hello Lua", "(.)(.)", "%2%1"))
--> eHll ouLa    4,將相鄰的兩個任意字符換位,共替換4次

當替換參數是函數時,會在每一次找到匹配時調用這個函數,並以捕獲的內容為參數,以這個函數返回值作為替換內容。

當替換參數是表時,會把第一個捕獲內容作為鍵,去查找表中的值作為替換內容,如果不成功,則當次不做任何替換。

例如:

tb={}
tb.Hello="+"
print (string.gsub ("Hello Lua", "%a+", tb))
--> + Lua    2, 以匹配到的字符序列為鍵去獲取表tb中對應該鍵的值,如果是標准字符串則使用這個字符串替換,如果沒找到鍵或者值不是字符串類型則不做改變。
本示例匹配到了2次但只替換1次。

 

小程序練習

-- 給定一個字符串,找出字符串中所有單詞並計算重復的次數,輸出前進行排序,優先輸出重復最多的單詞
do
    local txt = [[hi hi lua aaa b c c c cc]] -- 指定字符串
    local tbl = {}

    for key in string.gmatch(txt, "%a+") do  -- 每次迭代逐個捕獲表中單詞,存入表tbl
        tbl[key] = (tbl[key] or 0) + 1       -- 作為鍵存表,其值做一次計數自增
    end
    
    local words = {}
    for k, v in pairs(tbl) do                -- 把無序表tbl的鍵作為值按順序導入表words
        words[#words + 1] = k
    end

    table.sort (words, function(v1, v2) return tbl[v1] > tbl[v2] or tbl[v1] == tbl[v2] and v1 < v2 end)
    -- 排序表words,比較tbl中相關鍵的值(重復的次數),優先按次數最多排序,如果次數相等則按首字母順序排
    for _,v in ipairs(words) do              -- 遍歷數組輸出
        print ("單詞 "..v.." 被找到 "..tbl[v].."")
    end
end

--[[ 輸出結果
單詞 c 被找到 3 次
單詞 hi 被找到 2 次
單詞 aaa 被找到 1 次
單詞 b 被找到 1 次
單詞 cc 被找到 1 次
單詞 lua 被找到 1 次
--]]

 

學習輔助工具

Lua正則在線測試工具 (luatos.com)

LuatOS 在線模擬 - lua在線測試

 


免責聲明!

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



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