Lpeg
LPeg是一个为Lua所使用的新的模式匹配库,基于解析表达式语法(PEGs)。
- 用基本匹配函数,组合匹配表达式
- 所有匹配函数返回userdata类型,是一个匹配模式(以下用pattern代替),可相互组合.
Simple Matching 简单匹配
local lpeg = require "lpeg" local match = lpeg.match -- 对字符串匹配给定的模式 local P = lpeg.P -- 从字面上匹配一个字符串 local S = lpeg.S -- 匹配集合中的任何东西 local R = lpeg.R -- 匹配在一定范围内的任何东西 -- 匹配字符串的开头,成功则返回匹配之后的位置,失败返回nil print(match(P'a', 'aaa')) -->2 print(match(P'a', '123')) -->nil -- 匹配一个范围之内,匹配一个集合之内 print(match(R'09', '123')) -->2 print(match(S'123', '123')) -->2 -- 匹配一个以上的项 print(match(P'a'^1, 'aaa')) -->4 -- 符号*组合模式,匹配a之后,再匹配0或多个b print(match(P'a'*P'b'^0, 'abbc')) -->4 -- 组合模式,匹配一个或0个a,再匹配b local maybe_a = P'a'^-1 local match_ab = maybe_a * 'b' print(match(match_ab, 'ab')) -->3 print(match(match_ab, 'b')) -->2 print(match(match_ab, 'aaab')) -->nil -- 符号+匹配其中任意一个 local either_ab = (P'a' + P'b')^1 print(either_ab:match'aaa') -->4 print(either_ab:match'bbaa') -->5
Basic Captures 基本捕获
local lpeg = require "lpeg" local match = lpeg.match -- 对字符串匹配给定的模式 local P = lpeg.P -- 从字面上匹配一个字符串 local S = lpeg.S -- 匹配集合中的任何东西 local R = lpeg.R -- 匹配在一定范围内的任何东西 local C = lpeg.C -- 捕获匹配 local Ct = lpeg.Ct -- 一个从模式捕获过来的表 -- 捕获数字 local digit = R'09' -- 任何0到9的数 local digits = digit^1 -- 至少要有一个数字 local cdigits = C(digits) print(cdigits:match'123') -->123 -- 包含+-符号 local int = S'+-'^-1 * digits print(match(C(int), '+23')) -->+23 -- 对捕获的字符串通过一个功能 print(match(int/tonumber, '+123') + 1) -->124 -- 返回多个捕获,就像string.match print(match(C(P'a'^1) * C(P'b'^1), 'aabbbb')) -->aa bbbb
Building more complicated Patterns 构建更复杂的模式
local lpeg = require "lpeg" local match = lpeg.match -- 对字符串匹配给定的模式 local P = lpeg.P -- 从字面上匹配一个字符串 local S = lpeg.S -- 匹配集合中的任何东西 local R = lpeg.R -- 匹配在一定范围内的任何东西 local C = lpeg.C -- 捕获匹配 local Ct = lpeg.Ct -- 一个从模式捕获过来的表 -- 考虑一般的浮点数,等同于正则[-+]?[0-9]+\.?[0-9]+([eE][+-]?[0-9]+)? function maybe(p) return p^-1 end local digits = R'09'^1 local mpm = maybe(S'+-') local dot = '.' local exp = S'eE' local float = mpm * digits * maybe(dot * digits) * maybe(exp *mpm * digits) print(match(C(float), '2.3')) -->2.3 print(match(C(float), '-2')) -->-2 print(match(C(float), '2e-02')) -->2e-02 -- 从列表识别数字 local listf = C(float) * (',' * C(float))^0 print(listf:match'2,3,4') -->2 3 4 -- 放进实际的表 print(match(Ct(listf), '1,2,3')) -->table: 003FAEE0 local tList = match(Ct(listf), '1,2,3') for i = 1, #tList do print(tList[i]) end -->1 -->2 -->3 -- 转换类型 local floatc = float/tonumber listf = floatc * (',' * floatc)^0 -- 忽略空格 local sp = P' '^0 function space(pat) return sp * pat * sp end local floatc = space(float/tonumber) local listc = floatc * (',' * floatc)^0 print(match(listc, '1,2, 3')) -->1 2 3 -- 匹配标识符 function list(pat) pat = space(pat) return pat * (',' * pat)^0 end local idenchar = R('AZ', 'az') + P'_' local iden = idenchar * (idenchar + R'09')^0 print(list(C(iden)):match'hello, dolly, _x, s23') -->hello dolly _x s23 -- 使用语言环境无关定义 local l = {} lpeg.locale(l) for k in pairs(l) do print(k) end --[[ punct alpha alnum digit graph xdigit upper space print cntrl lower --]] iden = (l.alpha + P'_') * (l.alnum + P'_')^0 print(list(C(iden)):match'hello, dolly, _x, s23') -->hello dolly _x s23 -- 类似的CSV格式 local rlistf = list(float/tonumber) local csv = Ct((Ct(rlistf) + '\n')^1) local tcsv = csv:match'1,2.3,3\n10,20, 30\n' for i = 1, #tcsv do for j = 1, #tcsv[i] do print(tcsv[i][j]) end end --[[ 1 2.3 3 10 20 30 --]]
http://lua-users.org/wiki/LpegTutorial%20