Lua的字串匹配與正規表示式

2021-09-29 19:26:39 字數 4341 閱讀 3468

使用lua一段時間了,簡單總結下string庫中的幾個與正則相關的函式。這些函式是find,match, gmatch和gsub。然後是lua中支援的正則。文中的例子在lua5.3的命令列中試驗過。5.1版的需要在提示符前加乙個=號或加return空格。

string.find('hanazawa kana', 'na')

3 4string.find('hanazawa kana', '[%a]+')

1 8string.find('2015-5-12 13:53', '(%d+)-(%d+)-(%d+)')

1 9 2015 5 12

string.find('2015-5-12 13:53', '(%d+)-(%d+)-(%d+)', 1, true)

nilstring.find('%a1234567890%a', '%a', 3, true)

13 14

在字串s中匹配pattern,如果匹配失敗返回nil。否則,當pattern中沒有分組時,返回第乙個匹配到的子串;當pattern中有分組時,返回第乙個匹配到子串的分組,多個分組就返回多個。可選引數init表示匹配字串的起始索引,預設為1,可以為負索引。

> string.match('2015-5-12 13:53', '%d+-%d+-%d+')

2015-5-12

> string.match('2015-5-12 13:53', '(%d+)-(%d+)-(%d+)')

2015 5 12

> string.match('2015-5-12 13:53', '((%d+)-(%d+)-(%d+))')

2015-5-12 2015 5 12

可以發現,所有用到match的地方都可以用find來實現。match是find的乙個簡化版

返回乙個迭代器。每當迭代器呼叫時,返回下乙個匹配到的子串,如果pattern中有分組,返回的是子串對應的分組。gmatch也可以用find和迴圈來實現。

> for s in string.gmatch('2015-5-12 22:20', '%d+') do print(s) end

2015512

2220

> for s in string.gmatch('hanazawa kana', 'a(%a)a') do print(s) end --找出形如「a字母a」中間的字母nw

n> for k, v in string.gmatch('a=214,b=233', '(%w+)=(%w+)') do print(k, v) end

a 214

b 233

看上面第二個測試例子,處於兩個a字母中間的單個字母還有『z』,但迴圈並沒有輸出。原因是在'ana'匹配成功之後,接下來匹配是從'z'開始的,z沒有被匹配到。正確的模式pattern應該不要捕獲'a(%a)a'的後面的a,用python的正則可以寫成'a(\w)(?=a)',他不會消耗掉後面的a。但是lua不支援(?=...)。(python中\w表示單詞字元[a-za-z0-9_],記不清就把這類元字元列出來 如 %a寫成[a-za-z] 。)

替換字串函式!這個功能應該是字串處理中實用性最強的乙個。

把字串中用模式pattern匹配到的所有子串替換為repl指代的子串,返回替換後的字串和替換的次數。可選數值引數n表示最多可替換的次數。

引數repl可以是正規表示式,也可以是函式。當repl是函式時,函式的引數是模式pattern捕獲的子串,和match類似,有分組返回分組,無分組返回整個子串。函式最後應該返回乙個字串。如果repl是正規表示式,可以用分組序號引用匹配到的分組。

> string.gsub('hanazawa kana', 'na', 'nya')

hanyazawa kanya

> string.gsub('hanazawa kana', 'na', function(s) return string.sub(s,1,1)..'y'..string.sub(s,2,2) end)

hanyazawa kanya

> string.gsub('hanazawa kana', '(n)(a)', function(a,b) return a..'y'..b end)

hanyazawa kanya

> string.gsub('hanazawa kana', '(n)(a)', '%1y%2')

hanyazawa kanya

正規表示式由元字元按照規則(語法)組成。lua中的特殊字元是%.^$+-*?,一共12個。它們和一般字元按規則構成了lua的正規表示式。

元字元描述

表示式例項

完整匹配的字串

字元普通字元

除去%.()^$*+-?的字元,匹配字元本身

kana

kana

.匹配任意字元

ka.a

kana

%轉義字元,改變後乙個字元的原有意思。當後面的接的是特殊字元時,將還原特殊字元的原意。%和一些特定的字母組合構成了lua的預定義字符集。%和數字1~9組合表示之前捕獲的分組

k%wna

%%na%%

(a)n%1

kana

%na%

ana[...]

字符集(字元類)。匹配乙個包含於集合內的字元。[...]中的特殊字元將還原其原意,但有下面幾種特殊情況

1. %],%-,%^作為整體表示字元']','-','^'

2. 預定義字符集作為乙個整體表示對應字符集

3. 當]位於序列的第乙個字元時只表示字元']'

4. 形如[^...],[...-...]有特定的其他含義

[a%]na

[%a]na

[%%a]na

]na[%]]na

[a-]na

%nawna

wna]na

]na-na

[...-...]

-表示ascii碼在它前乙個字元到它後乙個字元之間的所有字元

[a-z]a

na[^...]

不在...中的字元集合。

[^0-9]na

[^^0-9]na

knakna

重複(數量詞)

*表示前乙個字元出現0次或多次

[0-9]*

[a-z]*9*

2009na+

表示前乙個字元出現1次或1次以上

n+[0-9]+

n2009

?表示前乙個字元出現0次或1次

n?[0-9]+

2009

預定義字符集

%s空白符[ \r\n\t\v\f]

an[%s]?9

an 9

%p標點符號

an[%p]9

an.9

%c控制字元

%w字母數字[a-za-z0-9]

[%w]+

kana9

%a字母[a-za-z]

[%a]*

kana

%l小寫字母[a-z]-%u

大寫字母[a-z]-%d

數字[0-9]-%x

16進製制數[0-9a-fa-f]-%z

ascii碼是0的字元-分組

(...)

表示式中用小括號包圍的子字串為乙個分組,分組從左到右(以左括號的位置),組序號從1開始遞增。

ab(%d+)

(%d+)%1

ab233

123123

邊界匹配(屬於零寬斷言)

^匹配字串開頭

^(%a)%w*

abc123

$匹配字串結尾

%w*(%d)$

abc123

%b%bxy

平衡匹配(匹配xy對)。這裡的x,y可以是任何字元,即使是特殊字元也是原來的含義,匹配到的子串以x開始,以y結束,並且如果從x開始,每遇到x,計算+1,遇到y計數-1,則結束的y是第乙個y使得計數等於0。就是匹配成對的符號,常見的如%b()匹配成對的括號

%b()

%d+%b()

(3+4(x*2))

2(3+4(x*2))

備註

lua不支援分組後面接重複詞(+*?),對於複雜的匹配可以用find+迴圈手動處理。

%bxy跟預定義字符集有區別,前者在[...]仍保持原意,後者則失去特殊意義

上表中是lua對正則的支援,其他的正則如命名組,重複等並不能在lua中用。注意轉義字元是%不是

參考

lua5.1參考手冊

python正規表示式指南(by astralwind)

正規表示式30分鐘入門教程(by deerchao)

正規表示式匹配字串

正規表示式用於字串處理 表單驗證等場合,實用高效。現將一些常用的表示式收集於此,以備不時之需。匹配中文字元的正規表示式 u4e00 u9fa5 評注 匹配中文還真是個頭疼的事,有了這個表示式就好辦了 匹配雙位元組字元 包括漢字在內 x00 xff 評注 可以用來計算字串的長度 乙個雙位元組字元長度計...

正規表示式匹配 字串

正規表示式匹配字串 假使,有幾個需要驗證的字串用 連線在一起 形如 farmer1,1farmer234 想用正規表示式來匹配每乙個字串。private static string sourcestr farmer1,1farmer234 private static string key farm...

字串 正規表示式匹配

此題出自牛客網的劍指offer專題 請實現乙個函式用來匹配包括 和 的正規表示式。模式中的字元 表示任意乙個字元,而 表示它前面的字元可以出現任意次 包含0次 在本題中,匹配是指字串的所有字元匹配整個模式。例如,字串 aaa 與模式 a.a 和 ab ac a 匹配,但是與 aa.a 和 ab a ...