阅读 129

lua字符串匹配

简单的单字符匹配

  • %a,匹配字母,无论大小写。
local str = "sdfe55IIYY993"
print(str:gsub("%a","0")) --- 0000550000993	8;所有字母全部替换
print(str:match("%a","0")) --- s
print(str:find("%a")) --- 1	1 ,其实找到的就是s
for s in str:gmatch("%a") do
    print(s)
end --s d f e I I Y Y
复制代码
  • %b 匹配对称字符,并,一般写法为"%bxy",x为开始匹配字符,y为结束匹配字符,xy可随意指定,并返回x..y及其内部的所有字符。
local str = "sdfe55IIYY993"
print(str:gsub("%bd5","0")) --- s05IIYY993	1  ; 匹配d和5及其中间的所有字符
print(str:match("%bd5","0")) --- dfe5
复制代码
  • %c 匹配控制字符 例如:换行符\n、制表符\t等
local str = "sdfe55IIYY\n993"
print(str:gsub("%c","0")) --- sdfe55IIYY0993	1;\n被替换为了0
print(str:gsub("%C","0")) -- 0000000000000	13
复制代码
  • %d 匹配数字0-9 ,类似于[0-9]
local str = "13900000000"
print(str:match("%d%d%d%d")) --- 1390
复制代码
  • %l 匹配小写字母a-z
local str = "sdfwe3334GGG"
print(str:gsub("%l","&")) -- &&&&&3334GGG	5
print(str:gsub("%L","&")) -- sdfwe&&&&&&&	7
复制代码
  • %p 匹配标点符号
local str = "sdfwe3,334,GG!G"
print(str:gsub("%p","&")) --- sdfwe3&334&GG&G	3
print(str:gsub("%P","&")) -- &&&&&&,&&&,&&!&	12
复制代码
  • %s 匹配空白符号,一般包括空格、换行符\n、制表符\t以及回到行首符\r
local str = "sdfwe3 3\n4,GG!G"
print(str:gsub("%s","&")) -- sdfwe3&3&4,GG!G	2
print(str:gsub("%S","&")) --&&&&&& &&&&&&&	13
复制代码
  • %u 匹配大写字母A-Z
local str = "sdfwe3 34,GG!G"
print(str:gsub("%u","&"))  -- sdfwe3 34,&&!&	3
print(str:gsub("%U","&"))  -- &&&&&&&&&&GG&G	11
复制代码
  • %w 匹配字母和数字
local str = "sdfwe3 34,GG!G"
print(str:gsub("%w","&")) -- &&&&&& &&,&&!&	11
print(str:gsub("%W","&")) -- sdfwe3&34&GG&G	3;这里有一个控股个,一个逗号,一个省略号
复制代码
  • %x 匹配十六进制数字
local str = "sdfwe3 Ef34,GG!G"
print(str:gsub("%x","&"))  --- s&&w&& &&&&,GG!G	8
print(str:gsub("%X","&")) --- &df&e3&Ef34&&&&&	8
复制代码
  • %z 匹配代表0的字符,需要用'\0'表示
local str = "sdfwe3 Ef34\0,GG!G"
print(str:gsub("%z","&"))  -- sdfwe3 Ef34&,GG!G	1
print(str:gsub("%Z","&")) -- &&&&&&&&&&&&&&&&	16
复制代码

以上字符类除了%b以外的大写形式表示取反,也就是取小写形式匹配集合的补集 例如:"%A"为匹配除字母外的其他字符,"%D"为匹配除数字外的其他字符

字符组合使用

local str= "sdfw099023jfsd"
print(str:match("%w%d%a")) -- 23j;一个字母或数字,一个数字,一个字母
print(str:gsub("%w%d%a","换")) -- sdfw0990换fsd	1
print(str:gsub("%d%d%d","换")) -- sdfw换换jfsd	2
复制代码

可以任意匹配组合多个元字符(也就是用来匹配的字符)。

修饰符

  • . 匹配任意字符
local str= "sdfw099023jfsd"
print(str:gsub(".","换")) -- 换换换换换换换换换换换换换换	14
复制代码
  • % 特殊字符的转义字符,例如:"%."为匹配点号,"%%"为匹配百分比符号,跟"""用来转义引号类似
local str= "sdfw099023.j%sd"
print(str:gsub("%.","换")) --- sdfw099023换j%sd	1
print(str:gsub("%%","换")) --- sdfw099023.j换sd	1
复制代码
  • () 匹配与返回括号内的内容,也就是将括号内的数据看成一个整体,若有一点不一样则匹配失败,如下面所写,字符串str中不含有090字串,所以匹配失败。
local str= "sdfw099023.j%sd"
print(str:gsub("(099023)","换")) -- sdfw换.j%sd	1
print(str:gsub("(090)","换")) -- sdfw099023.j%sd	0

--小案例,匹配五位数的qq号
local str1 = "12345@qq.com"
local str2 = "123456@qq.com"
local match = "(%d%d%d%d%d@qq.com)"
print(str1:match(match) == str1) -- true
print(str2:match(match) == str2) -- false

复制代码
  • [] 自定义匹配字符集,字符集可以由任意多个字符组成。 例如:"[a-z0-9,%]"匹配a-z、0-9、逗号以及百分比号,
local str= "sdfw099023.j%sd"
-- 匹配所有的数字和标点符号
print(str:gsub("[%d%p]","换")) --sdfw换换换换换换换j换sd	8
--小案例,替换a,b,c,d为零
local str = "adbcedadgadcewd"
print(str:gsub("[a-d]","0")) -- 0000e000g000ew0	11
--中的[a-d]相当于[abcd]
复制代码
  • + 匹配前一字符1次或多次
  • * 匹配前一字符0次或多次 最长匹配

+*很类似,唯一区别是*号支持零次,也就是说某些情况下*匹配的次数可能会多一些。例如:

local str = "_a_d_1_2_3_4"
print(str:gsub("_%d+","换")) -- _a_d换换换换	4
print(str:gsub("_%d*","换")) -- 换a换d换换换换	6
复制代码
  • - 匹配前一字符0次或多次 最短匹配

-*的区别在于一个是最短匹配,一个是最长匹配,要非常注意这个区别,否则会产生很大的错误,例如以lua程序设计上的例子为例:

local str = "int x; /*x*/ int y;/*y*/ "
print(str:gsub("%/%*.-%*%/","")) -- int x;  int y; 	2
print(str:gsub("/%*.-%*/","")) -- int x;  int y; 	2
print(str:gsub("%/%*.*%*%/",""))int x;  	1

--例如只是单纯的想把/**/这些注释去掉,而保留其他,这时需要用到`.-`,因为`.-`会尽可能短的匹配,
--所以/*会与最先遇到*/进行匹配;而使用`.*`会尽可能长的匹配,这时/*会与最后一个*/进行匹配;
-- 还有一点小细节可以注意到。若不确定一个字符是否又特殊含义,就可以使用转义字符%进行转移,
-- 例如上面的写法1.和写法2一样
复制代码
  • ? 匹配前一字符0次或1次
local str = "=-+23=-324==34"
print(str:gsub("[+-]?%d+","换")) -- =-换=换==换	3
print(str:gsub("[+-]+%d+","换")) -- =换=换==34	2
print(str:gsub("[+-]*%d+","换")) -- =换=换==换	3
--- 其中`?`代表匹配`+`或`-0`一次或零次,所以`=-+23`替换为了`=-换`,
--- 而`*`代表匹配`+`或`-0`次或多次,最长匹配,所以`=-+23`替换为了`=换`,而最后的`34`也被替换为了`换`
--- `+`代表匹配+`或`-0`一次或多次,所以最后的`34`没有被替换为了`换`
复制代码
  • ^ 匹配字符串开头 例如:"^%d+"为以数字开头的匹配;而在字符集[]中代表补集的意思,例如%d代表数字,[^%d]代表非数字。
local str = "=-+23=-324==34"
print(str:gsub("%d+","换")) -- =-+换=-换==换	3 ;匹配数字
print(str:gsub("[^%d]","换")) -- 换换换23换换324换换34	7 ;匹配非数字
print(str:gsub("^%p","换")) -- 换-+23=-324==34	1 ;匹配以标点符号开头,并返回开头的标点,进行替换,
---未匹配到,则返回nil
print(str:gsub("[^%d+-]","换")) -- 换-+23换-324换换34	4 ;匹配非数字,也不是`+`或`-`的串
复制代码
  • $ 匹配字符串结尾 例如:"%d+$"为以数字结尾的匹配
local str = "=-+23=-324==34"
print(str:gsub("%d+$","换")) -- =-+23=-324==换	1
print(str:gsub("%d$","换"))  -- =-+23=-324==3换	1;
-- 也体现了有`+`和无`+`的区别
复制代码

高级用法

  • 捕获,允许根据一个模式从目标字符串中抽出与该模式匹配的内容来用于后续,可以把需要捕获的部分放到一对圆括号内,一个小圆括号代表一个捕获,而且每个小括号中的内容会做为返回值返回,还可以使用%n,表示匹配第n个捕获的副本。例如%1代表第一个捕获的副本.
local str = [[he said:"it's all rihgt!"]]
print(str:match('([%"])(.-)%1'))
--"	it's all rihgt!
复制代码
  • 替换,若替换内容为字符串,则用字符串替换;若替换内容为表时,会把匹配到的第一个值作为key,去表中查询,并把查询到的内容作为值返回作为字符串;若替换内容为一个函数时,则用函数的返回值做为替换字符串,若返回值为nil,则不改变原字符串。
local str = "com{some text}"
print(str:gsub("(.-){(.-)}","<%1>%2<%1>")) --<com>some text<com>	1

tab = {com = "换",["some text"] = 45}
local str = "com{some text}"
print(str:gsub("(.-){(.-)}",tab)) -- 换	1

print(str:gsub("(.-){(.-)}",function(a,b)
   return a .. "--" .. b
end)) -- com--some text	1
复制代码