在Lua中使用正则表达式进行模式匹配的string库函数有这四个:
string.find(str, pattern[, init[, plain]])
string.gsub(str, pattern, repl[, n])
string.match(str, pattern[, init])
string.gmatch(str, pattern)
这几个函数的使用方法在前面Lua中string常用api用法整理已经介绍过了,这里就不赘述了!
在Lua中进行模式匹配的时候支持的字符类如下:
元字符 | 描述 | 备注 |
%a | 匹配字母,无论大小写 | |
%b | 匹配对称字符,一般写法为"%bxy",x为开始匹配字符,y为结束匹配字符,xy可随意指定 | 例如:"%b<>"为匹配包括<>在内的所有字符 |
%c | 匹配控制字符 | 例如:换行符\n、制表符\t等 |
%d | 匹配数字0-9 | |
%l | 匹配小写字母a-z | |
%p | 匹配标点符号 | |
%s | 匹配空白符号 | |
%u | 匹配大写字母A-Z | |
%w | 匹配字母和数字 | |
%x | 匹配十六进制数字 | |
%z | 匹配代表0的字符 | |
以上字符类除了%b以外的大写形式表示取反,也就是取小写形式匹配集合的补集 | 例如:"%A"为匹配除字母外的其他字符,"%D"为匹配除数字外的其他字符 | |
. | 匹配任意字符 | |
% | 特殊字符的转义字符 | 例如:"%."为匹配点号,"%%"为匹配百分比符号,跟"\""用来转义引号类似 |
() | 匹配与返回括号内的内容 | |
[] | 自定义匹配字符集 | 例如:"[a-z0-9,%]"匹配a-z、0-9、逗号以及百分比号 |
+ | 匹配前一字符1次或多次 | |
* | 匹配前一字符0次或多次 | 最长匹配 |
- | 匹配前一字符0次或多次 | 最短匹配 |
? | 匹配前一字符0次或1次 | |
^ | 匹配字符串开头 | 例如:"^%d+"为以数字开头的匹配 |
$ | 匹配字符串结尾 | 例如:"%d+$"为以数字结尾的匹配 |
普通元字符的例子:
-- %a
local str = "ab12"
print(string.gsub(str, "%a", "C")) -- CC12 2
print(string.gsub(str, "%A", "C")) -- abCC 2
-- %b
str = "12a<nice>bc"
print(string.match(str, "%b<>")) -- <nice>
-- %c
str = "s12\naaa\tbb"
print(string.gsub(str, "%c", "Y")) -- s12YaaaYbb 2
print(string.gsub(str, "%C", "Y"))
-- YYY
-- YYY YY 8
-- %d
str = "ab1c2d"
print(string.gsub(str, "%d", "6")) -- ab6c6d 2
print(string.gsub(str, "%D", "6")) -- 661626 4
-- %l
str = "AbA12Bc3"
print(string.gsub(str, "%l", "G")) -- AGA12BG3 2
print(string.gsub(str, "%L", "G")) -- GbGGGGcG 6
-- %p
str = "hello world!"
print(string.match(str, "%p")) -- !
print(string.match(str, "%P")) -- h
-- %s
str = "hello world!"
print(string.gsub(str, "%s", ",")) -- hello,world! 1
print(string.gsub(str, "%S", ",")) -- ,,,,, ,,,,,, 11
-- %u
str = "AbA12Bc3"
print(string.gsub(str, "%u", "U")) -- UbU12Uc3 3
print(string.gsub(str, "%U", "U")) -- AUAUUBUU 5
-- %w
str = "中文很6a"
print(string.gsub(str, "%w", "厉害")) -- 中文很厉害厉害 2
print(string.gsub(str, "%W", "厉害")) -- 厉害厉害厉害厉害厉害厉害厉害厉害厉害6a 9
-- %x
str = "MN1GeF"
print(string.gsub(str, "%x", "o")) -- MNoGoo 3
print(string.gsub(str, "%X", "o")) -- oo1oeF 3
-- %z
str = "0123489\0a"
print(string.gsub(str, "%z", "零")) -- 0123489零a 1
print(string.gsub(str, "%Z", "零")) -- 零零零零零零零 8
特殊元字符的例子:
-- .
local str = "a1&"
print(string.gsub(str, ".", "x")) -- xxx 3
-- %
str = "%ab*%%"
print(string.gsub(str, "%%", "x")) -- xab*xx 3
print(string.gsub(str, "%*", "y")) -- %aby%% 1
-- ()
str = "<body>主干</body>"
print(string.match(str, "<body>.+</body>")) -- <body>主干</body>
print(string.match(str, "<body>(.+)</body>")) -- 主干
-- []
str = "ab3cc8dmf,xx"
print(string.gsub(str, "[a5-8m-n,]", "z")) -- zb3cczdzfzxx 4
print(string.gsub(str, "[^a5-8m-n,]", "z")) -- azzzz8zmz,zz 8
--[[
说明:
"[^...]"会匹配不在...中的集合,即...的补集,例如"[^%d]"为匹配非数字字符,和"[%D]"效果一样
而"^..."匹配的是以...开头,例如"^%d+"为以数字开头的匹配
]]
-- ^
print(string.match("1abc", "^%d")) -- 1
print(string.match("a1bc", "^%d")) -- nil
-- $
print(string.match("abc1", "%d$")) -- 1
print(string.match("ab1c", "%d$")) -- nil
-- +
str = "ab12345ed"
print(string.match(str, "%d+")) -- 12345
-- * -
str = "<a><b><c>"
print(string.gsub(str, "<.*>", "{ok}")) -- {ok} 1
print(string.gsub(str, "<.->", "{ok}")) -- {ok}{ok}{ok} 3
--[[
说明:
*和-比较类似,只是*进行最长匹配,而-是进行最短匹配
所以在例子中使用*进行匹配的时候,会匹配第一个"<"到最后一个">"之间的所有内容进行替换,只匹配到了一次
而使用-进行匹配的时候,则会第一个"<"到第一个">"之间的内容进行替换,一共匹配到了3次
]]
-- ?
print(string.match("abc100", "[+-]?%d+")) -- 100
print(string.match("abc-100", "[+-]?%d+")) -- -100
print(string.match("abc+100", "[+-]?%d+")) -- +100
--[[
说明:
?是匹配前一字符0次或1次
在例子中即匹配字符类"[+-]"0次或1次,将这个匹配模式稍微改动一下,改成"^[+-]?%d+$"就可以检查这个字符串是否是整数了
]]
简单的应用:
-- 判断字符串是否为纯数字字符串
function judgeNumString(str)
return string.match(str, "%d+") == str
end
local str1 = "3497439"
local str2 = "83048a389b"
print(judgeNumString(str1), judgeNumString(str2)) -- true false
-- 判断是否是手机号码(大陆)
function judgePhoneNum(str)
return string.match(str,"[1][3-9]%d%d%d%d%d%d%d%d%d") == str
end
str1 = "13347823759"
str2 = "10348932849"
print(judgePhoneNum(str1), judgePhoneNum(str2)) -- true false
-- 判断微信号(微信帐号支持6-20个字母、数字、下划线和减号,必须以字母开头)
function judgeWechat(str)
return (string.match(str, "[A-Za-z][A-Za-z0-9_-]+") == str) and (#str >= 6 and #str <= 20)
end
str1 = "Wechat-666_S"
str2 = "Wechat*666"
print(judgeWechat(str1), judgeWechat(str2)) -- true false