lua的模式匹配

2021-06-21 16:09:49 字數 3235 閱讀 3503

原文:

lua 的模式匹配不使用posix規範的正規表示式(也寫做regexp)來進行模式匹配。主要的原因出於程式大小方面的考慮:實現乙個典型的符合posix標準的regexp大概需要4000行**,這比整個lua標準庫加在一起都大。權衡之下,lua中的模式匹配的實現只用了500行**,當然這意味著不可能實現posix所規範的所有更能。然而,lua中的模式匹配功能是很強大的,並且包含了一些使用標準posix模式匹配不容易實現的功能。

lua支援的所有字元類:

. 任意字元

%a 字母

%c 控制字元

%d 數字

%l  小寫字母

%p 標點字元

% s 空白符

%u 大寫字元

%w 字母和數字

%x 十六進製制數字

%z 代表0的字元

上面字元類的大寫形式表示小寫所代表的集合的補集。例如,'%a'非字母的字元:

print(string.gsub("hello, up-down!", "%a", "."))

--> hello..up.down. 4

例子:

s = "deadline is 30/05/1999, firm"

date = "%d%d/%d%d/%d%d%d%d"

print(string.sub(s, string.find(s, date))) --> 30/05/1999

在模式匹配中有一些特殊字元,他們有特殊的意義,lua中的特殊字元如下:

( )  .  % + - * ? [ ^ $

'%' 用作特殊字元的轉義字元,因此 '%.' 匹配點;'%%' 匹配字元 '%'。轉義字元 '%'不僅可以用來轉義特殊字元,還可以用於所有的非字母的字元。當對乙個字元有疑問的時候,為安全起見請使用轉義字元轉義他。

對lua而言,模式串就是普通的字串。他們和其他的字串沒有區別,也不會受到特殊對待。只有他們被用作模式串用於函式的時候,'%' 才作為轉義字元。所以,如果你需要在乙個模式串內放置引號的話,你必須使用在其他的字串中放置引號的方法來處理,使用 '/' 轉義引號,'/' 是lua的轉義符。

你可以使用方括號將字元類或者字元括起來建立自己的字元類(譯者:lua稱之為char-set,就是指傳統正規表示式概念中的括號表示式)。比如,'[%w_]' 將匹配字母數字和下劃線,'[01]' 匹配二進位制數字,'[%[%]]' 匹配一對方括號。

下面的例子統計文字中母音字母出現的次數:

_, nvow = string.gsub(text, "[aeiouaeiou]", "")

可以使用修飾符來修飾模式增強模式的表達能力,lua中的模式修飾符有四個:

+ 匹配前一字元1次或多次

* 匹配前一字元0次或多次

- 匹配前一字元0次或多次

? 匹配前一字元0次或1次

'+',匹配乙個或多個字元,總是進行最長的匹配。比如,模式串 '%a+' 匹配乙個或多個字母或者乙個單詞:

print(string.gsub("one, and two; and three", "%a+", "word"))

--> word, word word; word word

'%d+' 匹配乙個或多個數字(整數):

i, j = string.find("the number 1298 is even", "%d+")

print(i,j) --> 12 15

'*' 與 '+' 類似,但是他匹配乙個字元0次或多次出現.乙個典型的應用是匹配空白。

比如,為了匹配一對圓括號()或者括號之間的空白,可以使用 '%(%s*%)'。( '%s*' 用來匹配0個或多個空白。由於圓括號在模式中有特殊的含義,所以我們必須使用 '%' 轉義他。)再看乙個例子,'[_%a][_%w]*' 匹配lua程式中的標示符:字母或者下劃線開頭的字母下劃線數字序列。

'-' 與 '*' 一樣,都匹配乙個字元的0次或多次出現,但是他進行的是最短匹配。某些時候這兩個用起來沒有區別,但有些時候結果將截然不同。比如,如果你使用模式 '[_%a][_%w]-' 來查詢標示符,你將只能找到第乙個字母,因為 '[_%w]-' 永遠匹配空。另一方面,假定你想查詢c程式中的注釋,很多人可能使用 '/%*.*%*/'(也就是說 "/*" 後面跟著任意多個字元,然後跟著 "*/" )。然而,由於 '.*' 進行的是最長匹配,這個模式將匹配程式中第乙個 "/*" 和最後乙個 "*/" 之間所有部分:

test = "int x; /* x */ int y; /* y */"

print(string.gsub(test, "/%*.*%*/", ""))

--> int x;

然而模式 '.-' 進行的是最短匹配,她會匹配 "/*" 開始到第乙個 "*/" 之前的部分:

test = "int x; /* x */ int y; /* y */"

print(string.gsub(test, "/%*.-%*/", ""))

--> int x; int y;

'?' 匹配乙個字元0次或1次。舉個例子,假定我們想在一段文字內查詢乙個整數,整數可能帶有正負號。模式 '[+-]?%d+' 符合我們的要求,它可以匹配像 "-12"、"23" 和 "+1009" 等數字。'[+-]' 是乙個匹配 '+' 或者 '-' 的字元類;接下來的 '?' 意思是匹配前面的字元類0次或者1次。

與其他系統的模式不同的是,lua中的修飾符不能用字元類;不能將模式分組然後使用修飾符作用這個分組。比如,沒有乙個模式可以匹配乙個可選的單詞(除非這個單詞只有乙個字母)。下面我將看到,通常你可以使用一些高階技術繞開這個限制。

以 '^' 開頭的模式只匹配目標串的開始部分,相似的,以 '$' 結尾的模式只匹配目標串的結尾部分。這不僅可以用來限制你要查詢的模式,還可以定位(anchor)模式。比如:

if string.find(s, "^%d") then ...

檢查字串s是否以數字開頭,而

if string.find(s, "^[+-]?%d+$") then ...

檢查字串s是否是乙個整數。

'%b' 用來匹配對稱的字元。常寫為 '%bxy' ,x和y是任意兩個不同的字元;x作為匹配的開始,y作為匹配的結束。比如,'%b()' 匹配以 '(' 開始,以 ')' 結束的字串:

print(string.gsub("a (enclosed (in) parentheses) line",

"%b()", ""))

--> a line

常用的這種模式有:'%b()' ,'%b','%b%' 和 '%b<>'。你也可以使用任何字元作為分隔符。

Lua模式匹配

模式匹配函式 在string庫中功能最強大的函式是 string.find 字串查詢 string.gsub 全域性字串替換 string.gfind 全域性字串查詢 string.gmatch 返回查詢到字串的迭代器 這些函式都是基於模式匹配的。與其他指令碼語言不同的是,lua並不使用posix規...

Lua模式匹配

模式匹配函式 在string庫中功能最強大的函式是 string.find 字串查詢 string.gsub 全域性字串替換 string.gfind 全域性字串查詢 string.gmatch 返回查詢到字串的迭代器 這些函式都是基於模式匹配的。與其他指令碼語言不同的是,lua並不使用posix規...

Lua模式匹配

模式匹配函式 在string庫中功能最強大的函式是 string.find 字串查詢 string.gsub 全域性字串替換 string.gfind 全域性字串查詢 string.gmatch 返回查詢到字串的迭代器 這些函式都是基於模式匹配的。與其他指令碼語言不同的是,lua並不使用posix規...