lpeg
官网地址:http://www.inf.puc-rio.br/~roberto/lpeg/
LPeg是一个为Lua所使用的新的模式匹配库,基于解析表达式语法(PEGs)。
1.新建“Win32 Console Application”工程,工程名为:lpeg
2.在“Application Settings”中,选择“DLL”和“Empty project”
3.添加下载的“lpeg.h”、“lpeg.c”到工程中
4.菜单栏→“Project”→“Properties”,配置“All Configurations”,"Additional Include Directories"添加"...\Lua\5.1\include","Additional Library Directories"添加"...\Lua\5.1\lib","Additional Dependencies"添加"lua5.1.lib"
5.菜单栏→“Project”→“Add New Item”→“Modele-Definition File(.def)”,名称为:lpeg
6.“lpeg.def”的内容为:
1
2 |
LIBRARY "lpeg"
EXPORTS luaopen_lpeg |
7.编译Release版本
8.测试使用,新建一个lua脚本,内容为:
1
2 3 4 5 6 7 8 |
local lpeg = require "lpeg"
-- matches a word followed by end-of-string p = lpeg.R"az"^1 * -1 print(p:match("hello")) --> 6 print(lpeg.match(p, "hello")) --> 6 print(p:match("1 hello")) --> nil |
9.运行如下图所示:
Simple Matching 简单匹配
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
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 基本捕获
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
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 构建更复杂的模式
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
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 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 --]] |
参考资料:
1.http://www.inf.puc-rio.br/~roberto/lpeg/
2.http://lua-users.org/wiki/LpegTutorial