(轉)LUA正則表達式不完全指南


轉自劍俠論壇,並稍微修改個別文字。

 

 

 好不容易閑下來,研究了一下正則表達式,然后越鑽越深,經過跟大神們討論學習后,就沒有然后了。總之╮(╯▽╰)╭很有用的一個東西,至少對於用戶輸入的讀取方面會比較方便,所以就簡單舉例說說。

注:正則這個比較不好理解,經常容易轉不過彎來,個人覺得最好的學習方式就是自己去試,舉一反三,才會知道錯在哪里,我盡量提供不同種類同樣用法的例子方便理解。

正則表達式使用單個字符串來描述、匹配一系列符合某個句法規則的字符串。在很多文本編輯器里,正則表達式通常被用來檢索、替換那些符合某個模式的文本。(好吧,這是百度來的)
簡單來說就是按照一定想法獲取與替換字符串。想怎么換就怎么換(真的( ⊙o⊙ )?)

日常運用的時候,會遇到的情況比如某段話里帶有關鍵字,多個關鍵字等
“日常大戰xxx來治療”,“收xxx,帶價密”
這時候捕獲這些字符串下來進行分析與記錄,讓你不至於錯過某些不應該錯過的,或者說自動密那個人預定位置什么的……嗯,好像扯遠了,那是插件,今天只說lua。

元字符 描述
.   匹配任意字符,包括中文、字母、數字、符號等
% 特殊符號轉義,例如:%.為匹配點,%%為匹配百分比符號,跟“\”用來轉義引號是一樣的
%a alphabet,匹配字母,大小寫都匹配,%A為匹配除字母外其他字符
%b bisymmetric,匹配對稱字符,%bxy,x為開始匹配字符,y為結束匹配字符,xy可隨意指定。例如:%b<>為匹配包括<>在內的所有字符
%c control character,匹配控制字符,詳見百度,%C為匹配除控制字符外其他字符
%d digit,匹配數字,0到9,%D為匹配除數字外其他字符
%l lower case,匹配小寫字母a-z,%L為匹配小寫字母外其他字符
%p punctuation,匹配標點符號,%P為匹配標點符號外其他字符
%s space,匹配空白符號,包括\t(tab鍵四格空白),\n(新行的標示),\r(換行的標示),%S為匹配空白符號外其他字符
%u upper case,匹配大寫字母A-Z,%U為匹配大寫字母外其他字符
%w words,匹配字母和數字,%W為匹配字母和數字外其他字符
%x hex,匹配十六進制數字,%X為匹配十六進制數字外其他字符
%z zero,匹配代表0的字符,%Z為匹配0字符外其他字符
() 匹配與返回括號內的內容,例如:123(.+),匹配與返回帶有123字樣后續內容。詳見下
[] 自定義匹配字符集,例如:[a-z0-9,%.]匹配a到z以及0-9還有逗號,百分比號跟點,[^a-z0-9,%.]匹配除字符集以外的其他字符
+ 匹配前一字符1次或多次,常用於連貫性字符,例如:%a+ 以單詞為單位匹配
* 匹配前一字符0次或多次,最長匹配,常用於匹配空白符,例如%s*,將會匹配字符串內所有單個或者連貫空格
- 匹配前一字符0次或多次,最短匹配,在進行所有字符匹配時匹配最短,例如:|123|456|,用|(.*)|則會返回123|456,而|(.-)|則只返回123 
? 匹配前一字符0次或1次,例如:匹配正負數字,因為正數不帶負號
^ 匹配開頭,例如:^%d+為以數字開頭的匹配,可與匹配結尾一同使用
$ 匹配結尾,例如:%d+$為以數字開頭的結尾,可與匹配開頭一同使用

常用string操作:
參考資料:http://www.lua.org/manual/5.1/manual.html

string.find(s,pattern[,init[,plain]])
匹配第一個符合條件的項目的起始位置與終止位置,如果沒找到則返回nil
s代表目標字符串
pattern代表你要匹配的規則,見上面正則表格
init代表開始匹配的位置,默認為1,可以是負數,可不填
plain布爾值,如果為true時,則執行匹配任何匹配規則不生效,只是簡單的字面匹配

 


s = "%d+002929aciwe%a+cqoe01230"
local x,y = string.find(s,"%d+",1) --匹配數字,一次或多次連續
print(x,y)
--> x = 4, y = 9
s = "%d+002929aciwe%a+cqoe01230"
local x,y = string.find(s,"%d+",10) --匹配數字,一次或多次連續
print(x,y)
--> x = 22, y = 26
s = "%d+002929aciwe%a+cqoe01230"
local x,y = string.find(s,"%d+",1,true) --匹配字符"%d+"
print(x,y)
--> x = 1, y = 3
s = "%d+002929aciwe%a+cqoe01230"
local x,y = string.find(s,"%a+",1) --匹配字母,一次或多次連續
print(x,y)
--> x = 2, y = 2

 

s = "%d+002929aciwe%a+cqoe01230"
local x,y = string.find(s,"%a+",1,true) --匹配字符"%a+"
print(x,y)
--> x = 15, y = 17

 

string.match(s,pattern[,init])
匹配第一個符合條件的項目
s代表目標字符串
pattern代表你要匹配的規則,見上面正則表格
init代表開始匹配的位置,默認為1,可以是負數,可不填

 

s = "1number123xyz"
x = string.match(s,"%d+",1) --匹配數字,一次或多次匹配,從第一號位開始找
-->x = 1     --返回值是1
x = string.match(s,"%d+",2) --匹配數字,一次或多次匹配,從第二號位開始找
-->x = 123    --返回值是123
x = string.match(s,"%d+",-4) --匹配數字,一次或多次匹配,從右起第四號位開始向右找
-->x = 3
x = string.match(s,"%d+",-3) --匹配數字,一次或多次匹配,從右起第三號位開始向右找
-->x = nil

 

x = string.match(s,"%d*",-3) --匹配數字,零次或多次匹配,從右起第三號位開始向右找
--> 完成匹配,返回空白

string.gmatch(s,pattern)
返回迭代器,每次調用時會返回符合條件的項目和迭代器,如果沒有指定條件,返回整個字符串。
s代表目標字符串
pattern代表條件

 

s = "1number123xyz"
for x in string.gmatch(s,"%d+") do --匹配數字,一次或多次
print(x)
end
--> x = 1, x = 123
s = "1number123xyz"
for x in string.gmatch(s,"%d-") do --匹配數字,0次或多次,最短匹配,即0次
print(x)
end
-->完成匹配,返回空白
s = "1number123xyz"
for x in string.gmatch(s,"%d*") do --匹配數字,0次或多次,最長匹配
print(x)
end
-->1          123 --中間為空白

 


t = {}
s = "hello=123,         lua=456"
for k,v in string.gmatch(s,"(%w+)=(%w+)") do --匹配等號兩邊的數字與字母一次或多次,並且分別返回括號內的兩個值
t[k]=v
print(k,v)
end
--> hello     123
      lua       456
--> t= {["hello"]="123",["lua"]="456"}

string.sub(s,i[,j])
返回一項字符串的一部分
s為目標字符串
i為起始位置
j為終止位置,可不填,默認為-1,即使字串結束
i,j都可為負數

 

s = "我們是快樂的人啊!23333"
local x = string.sub(s,1,-6)
--> x="我們是快樂的人啊!"


重點介紹,最常用的
string.gsub(s,pattern,repl[,n])
返回因符合規則被全部或替換n次后的字符串,同時返回匹配成功次數
s為目標字符串
pattern為規則
repl為替換字符串,可為string,function,table。如果為string,則%在這里作為一個特殊符號,任何%1到%9代表會第幾次的返回值(這個返回值是一次匹配成功值下面會介紹),%1就是第一個值,%9則是第九個。而%0則是全部。而%%則表示百分比字符。如果repl是function,每次匹配成功將會調用函數,會將匹配到的字符串變為參數,如果沒有指定規則,則將整個字符串傳為一個參數。如果rep是table,則每次匹配成功都會與table進行比對,如符合array則替換為key值,如沒有規則,則以整個字符串作為比對。注:如果function和table的返回值是string或者數字,那么則替換,如果返回false或者nil則不進行替換。
n為執行幾次替換

s="先來最基礎簡單的"
x = string.gsub(s,"基礎簡單","復雜困難") --將"基礎簡單"替換成"復雜困難"
--> x = "先來最復雜困難的"
s="多次替換數字123,多次替換數字321"
x = string.gsub(s,"%d+","lalala") --將數字替換成"lalala"
--> x = "多次替換數字lalala,多次替換數字lalala"
s="本末&倒置,開始=逆轉"
x = string.gsub(s,"(.+)&(.+),(.+)=(.+)","%3%2%4%1") --一次匹配下返回括號內四個值,並且排列后替換整個字符串
--> x = "開始倒置逆轉本末"

%1-%4相當於臨時變量,將臨時變量賦予括號內的值並且將整個字符串替換成臨時排列后的變量。
%1 = 本末,%2 = 倒置,%3=開始,%4=逆轉,而%0則是等於整個字符串:本末&倒置,開始=逆轉

s="hello string test world"
x = string.gsub(s,"(%w+)%s*(%w+)","%1",1) --一次匹配返回兩個值,將這兩個替換成第一個值,只執行一次
--> x = "hello test world"

由於(%w+)%s*(%w+) 是匹配兩個單詞為一對,那么在例子里面符合條件的有兩對,一個是hello string以及test world。首先匹配到hello string返回兩個值%1=hello,%2=string,然后將整個hello string替換成hello。而由於值執行一次,所以第二對匹配成功的則不進行替換

s="hello string test world"
x = string.gsub(s,"(%w+)%s*(%w+)","%0 %0",1) --匹配成功后將多復制一次,只執行一次
--> x = "hello string hello string test world"

匹配成功的是hello string,兩個%0代表這個hello string會出現兩次,也就是這個結果了。

 

pattern為函數的,如下例:

function a(s)
return loadstring(s)()
end
x = string.gsub("2+6 = $return 2+6$", "%$(.-)%$",a)
--> x = "2+6 = 8"

pattern為table的,如下例:


local t = {name="lua", version="5.1"}
x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t) --匹配table內的項目並且替換掉原有的
--> x="lua-5.1.tar.gz"

 

說了這么半天,正則主要是看怎么定下規則,其他的應用都聽簡單的,至於規則的熟悉則要多練習,多實驗才能體會到。

實際范例:
文本 = 我切,我切|我切。我切@我切切切
規則 = [^,。@|]+
結果 = 我切 我切 我切 我切 我切切切 (gmatch)

文本 = 討   厭的  空格T _  T
規則 = %s*
結果 = 討厭的空格T_T (gsub)

文本 = a=3,    不作死=就不會死。  你要怎么=列表
規則 = ……你居然想一步把這個分開,果然作死
第一步:用%s*去掉所有空格
第二步:將分隔符去掉利用"切切范例"
第三步:將等號去掉並為table導入鍵值
結果  = {[a]=3,["不作死"]="就不會死",["你要怎么"]="列表"}

遇到不能一次分開的可以進行多次分割,若是動態文本則最好先轉一個固定的格式。基本上處理字符串先是要格式比較好,后續處理才比較簡單。至於-*+這三個的區別用處得多熟練,因為這三個很相似,所以很容易搞亂= =實在弄不清楚開SCITE去試試╮(╯▽╰)╭
愉快的一天又過去了╮(╯▽╰)╭
什么!居然寫了一天!?o(>﹏<)o

 

我的小結:

match找到的內容,find找到的結果,sub子串

函數名前有g表示全局,即對整個字符串處理,分割字符串可以用string.gsub。

 

 

 


免責聲明!

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



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