Lua正则表达式
Lua的正则表达式不是标准的Posix的标准实现,有自己的一些标准,由于长时间不使用,最近用到一个相关的业务逻辑,在一个标签中提取价格,但是这个标签是不规则的,可能前后有很多其他字符(¥XXX priceNum XXX),用固定长度截取显然不成,想到了用正则,最后google了一下,才搞定,但是发现很多都忘记了,这里记录一下。
相关库函数
string.find 字符串查找,匹配第一个符合条件的位置与最终位置
string.gfind是5.0中的函数,在5.1是被标记为deprecated的,在5.2被移除,替换为string.gmatch
string.match 匹配第一个符合的字符串
string.sub 截取字符串的一部分
string.gsub 全局字符串替换,替换目标字符串多次,返回替换后的字符串,同时返回的匹配替换的次数
string.gmatch 全局字符串查找,匹配多次符合条件的,并返回一个迭代器,可以在一个for循环里得到所有的匹配
Lua正则元字符
字符类
% 转义符,转义其他的有特殊意义的元字符串,转义双引号(“)使用反斜杠(\)
. 匹配任意字符
%a 所有字母
%b 边界匹配 如%bse,匹配以s开头e结尾中间的所有
%c 控制字符,类似响铃,退格,具体参照Wiki
%d 所有数字
%l 所有小写
%u 所有大写
%p 标点符号
%s 空白字符,包括空格,四格制表,换行(\r,\n)
%w 字母和数字
%x 十六进制数字
%z 表示0的字符
大写表示其补集,如%P,表示所有不是标点的。
字符集表示
使用一对中括号[],中括号内是对应的集合,可以使用-(中划线)表示一个范围
[0-9A-Za-Z]表示所有字母与数字
匹配次数指示
指示对应的模式匹配几次
+ 匹配其前面的pattern一次或者多次,按最多长匹配
* 匹配其前面的pattern0次或者多次,按最长匹配
- 匹配其前面的pattern0次或者多次,按最短匹配
? 匹配其前面的pattern0次或者一次
匹配开头和结尾
- 开头,使用^,如^x,匹配以x开头的模式
- 结尾,使用$,如x$,匹配以x结尾的模式
捕获指定内容
使用一对小括号(),捕获指定的内容并返回,用小括号括起对应的模式串
Example
获取标签内价格
开头说的获取标签内的价格信息,就可以使用string.match匹配对应的字符串,使用小括号捕获想要的内容,使用转义符%转义价格中可能出现的小数点,小数点后可能有数字也可能是一个整数价格,使用*来匹配0个或者多个小数点后的数字,小数前是一定有价格的,不然就不是价格标签了,使用+来匹配至少一个数字,最终得到如下正则表达式:
pattern = “(%d+%.%d*)”
1
2
3
4local moneyLabel = "¥ 666.02 - 元"
-- 获取666.02这个价格
local price = string.match(moneyLabel, "(%d+%.?%d*)")
print(price) -- 输出666.02string.gsub,模式串替换
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18local str = "worse is better"
local dest, count = string.gsub(str, "%a+", "lua")
-- 三个单词都被替换成lua,替换次数是3
print(dest .. " replace count = " .. tostring(count))
local gsubStr = " something with space "
-- 第三个参数,捕获对应的前面第几个分组内的匹配串
local trimStr = string.gsub(gsubStr, "^%s*(.-)%s*$", "%1")
print(trimStr)
local matchString = "1 2 3 4"
-- 第三个参数是把对应前的面捕获的1个替换为4个重复的
local repeatString = string.gsub(matchString, "(%d+)%s*", "%1 %1 %1 %1 ")
-- 第个参数表示执行几次替换
local repeatStringCount = string.gsub(matchString, "(%d+)%s*", "%1+", 2)
print(repeatString)
print(repeatStringCount)string.match,匹配串,首次匹配的结果,不是位置
1
2
3
4
5local tmp = "first1 second2 thrid3"
local resFromBehind = string.match(tmp, "%d", -2)
local res = string.match(tmp, "%D+")
print(resFromBehind) -- 输出3,最后参数指定由右侧第二字符开始匹配
print(res) -- 输出first,即非数字的其他字符一个或者多个,+是贪婪模式string.find,串查找,首次查找的位置,返回起始结束位置
1
2
3
4
5
6local findStr = "phone number: 19922337755"
-- 第三个参数是查找的起始位置,默认由1开始
local startIndex, endIndex = string.find(findStr, "%d+", 1)
print(startIndex, endIndex) -- 输出 15, 25
local result = string.sub(findStr, startIndex, endIndex)
print(result) -- 输出 19922337755string.gmatch,串匹配,返回一个迭代器,多次匹配
1
2
3
4
5
6
7
8
9
10
11
12
13local gmatchStr = "one1, two2, three3, four4, five5"
-- 包含字母和数字的单词
for word in string.gmatch(gmatchStr, "%w+") do
print(word)
end
-- 只包含字母的单词
for onlyLetters in string.gmatch(gmatchStr, "%a+") do
print(onlyLetters)
end
-- 只要数字
for onlyNums in string.gmatch(gmatchStr, "%d+") do
print(onlyNums)
end
记录完毕