前面的部分见 Lua 学习笔记(上)javascript
辅助库为咱们用 Lua 与 C 的通讯提供了一些方便的函数。基础 API 提供 Lua 与 C 交互的全部原始函数。辅助库做为更高层次的函数来解决一些通用的问题。html
辅助库的全部函数定义在头文件 luaxlib.h
中,函数带有前缀 luaL_
。java
辅助库函数是创建在基础库之上的,因此基础库作不了的事情辅助库也作不了。git
有一些函数是用来检查函数参数的,这些函数都有这样的前缀 luaL_check
或者 luaL_opt
。这些函数在检查出问题后会抛出错误。因为抛出的错误消息代表是参数错误(例如,“bad argument #1”),所以不要把这些函数用在参数之外的 Lua 值上。程序员
标准 Lua 库提供了许多有用的函数,这些函数都是直接用 C API 实现的。有一些函数提供了 Lua 语言自己所必要的服务(例如,type
和 getmetatable
);有一些提供了通向“外部”的服务(例如,I/O);还有一些函数,能够由 Lua 进行实现,可是因为至关有用或者有重要的性能需求须要由 C 实现(例如 sort
)。github
全部的库都以 C 模块的形式分开提供。5.1中,Lua有如下几种标准库:segmentfault
- 基础库 - 包库 - 字符串操做库 - 表操做库 - 数学功能库 - 输入输出库 - 操做系统工具库 - 调试工具库
除了基础库和包库,其余库都是做为全局表的域或者对象的方法提供。闭包
[待补充]socket
基础库为 Lua 提供了一些核心函数。若是没有包含这个库,那么就可能须要本身来实现一些 Lua 语言特性了。ide
若是其参数 v
的值为假(nil
或 false
), 它就调用 error
; 不然,返回全部的参数。 在错误状况时, message
指那个错误对象; 若是不提供这个参数,参数默认为 "assertion failed!" 。
assert(5==4,"Number Not Equal!") --> 报错 Number Not Equal!
assert(nil) --> 报错 assertion failed!
控制垃圾回收器的参数有两个,pause 和 step multipier。
参数 pause 控制了收集器在开始一个新的收集周期以前要等待多久。 随着数字的增大就致使收集器工做工做的不那么主动。 小于 1 的值意味着收集器在新的周期开始时再也不等待。 当值为 2 的时候意味着在总使用内存数量达到原来的两倍时再开启新的周期。
参数 step multiplier 控制了收集器相对内存分配的速度。 更大的数字将致使收集器工做的更主动的同时,也使每步收集的尺寸增长。 小于 1 的值会使收集器工做的很是慢,可能致使收集器永远都结束不了当前周期。 缺省值为 2 ,这意味着收集器将之内存分配器的两倍速运行。
该函数是垃圾回收器的通用接口,根据 opt
参数的不一样实现不一样的功能。
arg
控制(值越大,步数越多,0 表示执行一步(指最小的一步))。若是执行后完成了回收循环,返回 true
。进行垃圾回收先后的内存占用状况:
x = collectgarbage("count") print(x) --> 27.5615234375 collectgarbage("collect") x = collectgarbage("count") print(x) --> 26.7490234375
打开该名字的文件,并执行文件中的 Lua 代码块。 不带参数调用时, dofile 执行标准输入的内容(stdin)。 返回该代码块的全部返回值。 对于有错误的状况,dofile 将错误反馈给调用者 (即,dofile 没有运行在保护模式下)。
同一目录下新建两个 Lua 文件,代码及输出:
-- another.lua return "Message from another file!" -- sample.lua x = dofile("./another.lua") print(x) --> Message from another file!
dofile 在这里等价于
function dofile() function func() return "Message from another file!" end return func() end
因而等价的输出为
print(dofile()) --> Message from another file!
终止所保护的函数,抛出 message 消息,再也不返回。
一般这个函数会在抛出的消息前面加上发生错误的地址信息。堆栈等级决定添加哪一个地址。若是堆栈等级为 0 ,不返回地址信息;若是为 1,返回 error 语句所在位置;若是为 2,返回调用 error所在函数的位置;依此类推。
error([报错消息],[堆栈等级]=1)
function division(a,b) if b == 0 then error("Divisor cannot be 0!",2) end -- level 值为 1 时,错误信息指向这里 return a / b end print(division(5,1)) print(division(5,0)) -- level 值为 2 时,错误信息指向这里
_G
_G
持有全局环境的变量,Lua 自己用不到这个变量,更改变量不会影响到全局环境;反过来也同样。
返回函数的环境。 f 能够是一个 Lua 函数,也能够是函数在堆栈中的等级。等级 1 表明调用 getfenv() 的那个函数。若是传入的函数不是 Lua 函数,或者 f 是 0,那么 getfenv 返回 全局环境。
~~[待补充]不是太明白,没能给出合适的代码~~
参考 Lua中的环境概念
getfenv([目标函数]=1)
获取全局环境:
for k,v in pairs(_G) do print(k,v) end --string table: 0x7ff200f02330 --xpcall function: 0x7ff200d03cc0 --package table: 0x7ff200e00000 --tostring function: 0x7ff200d04560 --print function: 0x7ff200d046a0 --os table: 0x7ff200f01cb0 --unpack function: 0x7ff200d04610 --require function: 0x7ff200f006f0 --getfenv function: 0x7ff200d042f0 --setmetatable function: 0x7ff200d044a0 --next function: 0x7ff200d04260 --assert function: 0x7ff200d03fc0 --tonumber function: 0x7ff200d04500 --io table: 0x7ff200f014a0 --rawequal function: 0x7ff200d046f0 --collectgarbage function: 0x7ff200d04010 --arg table: 0x7ff200e01360 --getmetatable function: 0x7ff200d04340 --module function: 0x7ff200f006a0 --rawset function: 0x7ff200d047a0 --math table: 0x7ff200e00040 --debug table: 0x7ff200e00a00 --pcall function: 0x7ff200d042b0 --table table: 0x7ff200f00790 --newproxy function: 0x7ff200d04820 --type function: 0x7ff200d045c0 --coroutine table: 0x7ff200d048c0 --_G table: 0x7ff200d02fc0 --select function: 0x7ff200d04400 --gcinfo function: 0x7ff200d03000 --pairs function: 0x7ff200d03e00 --rawget function: 0x7ff200d04750 --loadstring function: 0x7ff200d04200 --ipairs function: 0x7ff200d03d70 --_VERSION Lua 5.1 --dofile function: 0x7ff200d04110 --setfenv function: 0x7ff200d04450 --load function: 0x7ff200d041b0 --error function: 0x7ff200d04160 --loadfile function: 0x7ff200d043a0
若是对象没有元表,返回空;若是对象有 __metatable
域,返回对应的值;不然,返回对象的元表。
对象有 __metatable
域的状况:
t = {num = "a table"} mt = {__index = {x = 1,y = 2},__metatable = {__index = {x = 5,y = 6}}} setmetatable(t, mt) print(getmetatable(t).__index.x) --> 5 print(t.x) --> 1
~~进行操做时的元表依旧是与值直接关联的那个元表,不知道这样子处理有什么做用?~~
返回三个值:迭代器、传入的表 t、值 0 。迭代器可以根据传入的表 t 和索引 i 获得 i+1 和 t[i+1] 的值。
其实现形式相似于这样:
function ipairs(t) function iterator(t,i) i = i + 1 i = t[i] and i -- 若是 t[i] == nil 则 i = nil;不然 i = i return i,t[i] end return iterator,t,0 end
使用 ipairs 对表进行遍历,会从键值为 1 开始依次向后遍历,直到值为 nil。
t = {"1","2",nil,[4]="4"} -- t = {"1","2",[4]="4"} -- 使用该表会获得相同的输出 for i,v in ipairs(t) do print(i,v) end --> 1 1 --> 2 2
经过传入函数 func 的返回值获取代码块片断。func 函数的后一次调用返回的字符串应当能与前一次调用返回的字符串衔接在一块儿,最终获得完整的代码块。函数返回 nil 或无返回值时表示代码块结束。
load 函数会将获得的代码块做为函数返回。返回函数的环境为全局环境。若是出现错误,load 会返回 nil 和 错误信息。
chunkname 做为该代码块的名称,用在错误信息与调试信息中。
[待补充]
使用方式与 dofile 相似,函数内容与 load 相似。从文件中获取代码块,若是没有指定文件,则从标准输入中获取。
loadfile 把文件代码编译为中间码,以文件代码做为一个代码块(chunk),并返回包含此代码块的函数。
编译代码成中间码,并返回编译后的chunk做为一个函数。 若是出现错误,则返回 nil 以及错误信息。
使用 loadfile,能够一次编译屡次运行;而每次使用 dofile,都会执行一次编译。
同一目录下新建两个 Lua 文件,代码及输出:
-- sample.lua f = loadfile("./sample.lua") print(f()) --> Message from another file! --> 0 -- another.lua function fun() print("Message from another file!") return 0 end res = fun() return res
loadfile 在这里等价于
function loadfile() function fun() print("Message from another file!") return 0 end res = fun() return res end
与 load 相似,只不过是从字符串中获取代码块。
要想加载并运行所给的字符串,使用以下惯用形式:
assert(loadingstring(s))()
返回传入的表中下一个键值对。
next([表],[键]=nil)
第一个参数是要操做的表,第二个参数是表中的某个键。若是传入的键值为 nil ,则函数返回第一个键值对。若是传入一个有效的键值,则输出下一对键值对。若是没有下一个键值对,返回 nil。
根据定义,可使用 next 来判断一个表是否为空表。
注意:
键值对的遍历顺序是不必定的,即便是对数字索引也是如此。若是想要按照数字索引的顺序获取键值对,参见 ipairs (t) 函数。
t = {"table",["a"] = 5, ["c"] = 6} -- index 为 nil print(next(t, nil)) --> 1 table -- index 为 无效键 print(next(t,"d")) --> 编译错误 -- index 为 数字索引 print(next(t,1)) --> a 5 -- index 为 通常键 print(next(t, "a")) --> c 6 -- index 为 最后一个键 print(next(t,"c")) --> nil
遍历顺序与定义顺序不一致的例子:
t = {[1]="table",b = 4,["a"] = 5, ["c"] = 6, func} t.func = function (...) return true end for k,v in pairs(t) do print(k,v) end --> a 5 --> func function: 0x7f7f63c0ad50 --> c 6 --> b 4
并且从上面的例子中能够看出 name = exp
的键值对形式会占用
返回三个值:next 函数,表 t,nil。一般用来遍历表中的全部键值对。
若是 t 有元方法 __pairs ,将 t 做为参数 传入该函数并返回前三个返回值。
在使用 pairs 函数遍历表的过程当中,能够删除域或者修改已有的域,可是若是添加新的域,可能出现没法预期的问题。
t = {"table",["a"] = 5, ["c"] = 6} for k,v in pairs(t) do print(k,v) end --> 1 table --> a 5 --> c 6
在遍历表的过程当中添加新的域致使问题出现的状况:
t = {"table",["a"] = 5, ["c"] = 6} for k,v in pairs(t) do -- 添加一个新的域 if k == 'a' then t[2] = 8 end print(k,v) end --> 1 table --> a 5
以保护模式调用传入的函数,也就是说不会抛出错误。若是捕获到抛出的错误,第一个参数返回 false,第二个参数返回错误信息;若是没有出现错误,第一个参数返回 ture,后面的参数返回传入函数的返回值。
function fun(a,b) assert(not(b == 0), "divisor can't be 0 !") return a / b end success, res = pcall(fun,5,0) --> false .../sample.lua:3: divisor can't be 0 ! success, res = pcall(fun,5,1) --> true 5
仅做为快速查看某个值的工具,不用作格式化输出。正式的格式化输出见 string.format 与 io.write。
以 raw
做为前缀的函数均表示该方法在不触发任何元方法的状况下调用。
rawequal 检查 v1 是否与 v2 相等,返回比较结果。
t = {"value"} s = "value" s2 = "value" print(rawequal(t, s)) --> false print(rawequal(s, s2)) --> true
获取 table 中键 index 的关联值,table 参数必须是一个表,找不到返回 nil 。
t = {"value",x = 5} print(rawget(t, 1)) --> value print(rawget(t, "x")) --> 5 print(rawget(t, 2)) --> nil print(rawget("value",1))--> bad argument #1 to 'rawget' (table expected, got string)
将 table[index] 的值设置为 value 。table 必须是一张表,index 不能是 nil 或 NaN 。value 能够是任何值。返回修改后的 table 。
t = {"value",x = 5} t2 = {"sub table"} rawset(t, 1,"new value") rawset(t, "y", 6) rawset(t, t2,"sub table") rawset(t,NaN,"NaN") --> table index is nil print(t[1]) --> new value print(t.y) --> 6 print(t[t2]) --> sub table
index 能够是数字或者字符 '#' 。当 index 为数字时,返回第 index + 1 个参数及后面的参数(支持负数形式的 index);当 index 为 '#' 时,返回参数的个数(不包括第一个参数)。
t = {"table",x = 5} t2 = {"table2"} print(select( 1, 1, t, t2)) --> 1 table: 0x7fad7bc0a830 table: 0x7fad7bc0ac20 print(select( -3, 1, t, t2)) --> 1 table: 0x7fad7bc0a830 table: 0x7fad7bc0ac20 print(select("#", 1, t, t2)) --> 3
设置函数 f 的环境表为 table 。f 能够是一个函数,或者是表明栈层级的数字。栈层级为 1 的函数是那个调用 setfenv 的函数,栈层级为 2 的函数就是更上一层的函数。 setfenv 返回 f。
特别的,若是 f 为 0,那么 setfenv 会把全局环境设置为 table 。而且不作任何返回。
Lua 的以后版本中去掉了 setfenv 和 getfenv 函数。
使用栈层级操做 setfenv 的例子:
function foobar(...) -- 设置 foobar 的环境 t = {} setmetatable(t, {__index = _G }) setfenv(1,t) a = 1 b = 2 -- 输出 foobar 的环境 for k,v in pairs(getfenv(1)) do print(k,v) end print() function foo(...) -- 设置 foo 的环境,继承 foobar 的环境 local t = {} setmetatable(t, {__index = _G}) setfenv(1,t) x = 3 y = 4 -- 输出 foo 的环境 for k,v in pairs(getfenv(1)) do print(k,v) end print() -- 再次设置 foobar 的环境 setfenv(2, t) end foo() -- 再次输出 foobar 的环境 for k,v in pairs(getfenv(1)) do print(k,v) end end foobar() --> a 1 --> b 2 --> --> y 4 --> x 3 --> --> y 4 --> x 3
将 setfenv 用于模块加载:
-- sample.lua 文件 local FuncEnv={} -- 做为环境 setmetatable(FuncEnv, {__index = _G}) -- 为了可以访问本来全局环境的值,将全局环境表(_G)放在元表中 local func=loadfile("other.lua") -- 返回一个函数,函数以 other 文件内容做为代码块 setfenv(func,FuncEnv) func() -- 执行代码块,获得定义的 message 函数,该函数会存在环境中 FuncEnv.message() --经过环境调用函数,FuncEnv 此时就至关于一个独立模块
-- other.lua 文件 function message() print("Message from another file!") end
本小节参考了 斯芬克斯 的 设置函数环境——setfenv ,icyday 的 lua5.1中的setfenv使用 两篇博客。
给 table 关联元表 metatable 。返回参数 table 。
若是元表定义了 __metatable
域,会抛出错误。
metatable 参数为 nil 表示解除已经关联的元表。
-- 关联一个定义了加法操做的元表 t = setmetatable({}, {__add = function(a,b) if type(a) == "table" and type(b) == "table" then return a.num + b.num end end}) t.num = 5 t2 = {num = 6} print(t+t2) --> 11 -- 只要有一个表进行了关联就可以进行运算 setmetatable(t, nil) -- 解除关联后再进行加法运算会报错 print(t+t2) --> attempt to perform arithmetic on global 't' (a table value)
tonumber([值],[基数]=10)
尝试把 e 转换为十进制数值并返回。若是没法转换返回 nil 。
base 表示传入参数的进制,默认为 10 进制。base 的可输入范围 [2,36]。高于 10 的数字用字母表示,A-Z 分别表示 11-35 。
print(tonumber(123)) --> 123 print(tonumber("123")) --> 123 print(tonumber("abc")) --> nil print(tonumber("abc", 20)) --> 4232 print(tonumber("ABC", 20)) --> 4232
能将任意类型的值转换为合适的字符串形式返回。要控制数字转换为字符串的方式,使用 string.format(formatstring,...) 。
若是值所关联的元表有 __tostring
域,则使用该域的元方法获取字符串。
function func() print("this is a function") end t = {name = "table"} print(tostring(123)) --> 123 print(tostring("abc")) --> abc print(tostring(func)) --> function: 0x7f86348013b0 print(tostring(t)) --> table: 0x7f86348013e0
返回 v 的类型,类型以字符串形式返回。 有如下八种返回值: "nil" , "number", "string", "boolean", "table", "function", "thread", "userdata"。
type(nil) --> "nil" type(false) --> "boolean" type(123) --> "number" type("abc") --> "string" print(type(nil) == "nil") --> true
unpack([列表],[起始位置]=1,[返回个数]=[列表长度])
返回表中的各个域的值,等价于返回
return list[i], list[i+1], ···, list[j]
t = {1,2,3,a = 4,b = 5} print(unpack(t, 1, 4)) --> 1 2 3 nil
包含有当前解释器版本号的全局变量,当前版本的值为 "Lua 5.1"。
与 pcall (f, arg1, ...) 相似。不一样的是,若是 f 函数抛出了错误,那么 xpcall 不会返回从 f 抛出的错误信息,而是使用 err 函数返回的错误信息。
function fun(a,b) -- 这里的参数没什么实际做用,就是展现下用法 error("something wrong !!", 1) end -- pcall local success, res = pcall(fun,1,2) print(success,res) --> false .../sample.lua:2: something wrong !! -- xpcall local success, res = xpcall(fun,function() return "an error occured !!" end,1,2) print(success,res) --> false an error occured !!
字符类表明一组字符。能够用下列组合来表示一个字符类。
组合 | 表明字母 | 表明字符类型 |
---|---|---|
x | (变量 x) | ^$()%.[]*+-? 之外的任一字符 |
. | (dot) | 任意字符 |
%a | (alphabet) | 字母 |
%b | (bracket) | 对称字符以及字符间的内容 |
%c | (control) | 控制字符(即各种转义符) |
%d | (digits) | 数字 |
%l | (lowercase) | 小写字母 |
%p | (punctuation) | 标点符号 |
%s | (space) | 空格 |
%u | (uppercase) | 大写字母 |
%w | (word) | 字母和数字 |
%x | (hexadecimal) | 十六进制字符 |
%z | (zero) | 值为 0 的字符,即 '\0' |
%x | (变量 x) | 字母和数字之外的任一字符 |
若是组合中的字符写成大写形式(例如将 '%a' 写成 '%A'),至关于对原来所表明的字符类型取补集。
例子:
前两行的数字标出每一个字符的下标。find函数返回找出第一个符合查找条件的字符的下标。
-----------------00000000001111111112 222222222333333333344444444445555 5 -----------------12345678901234567890 123456789012345678901234567890123 4 x = string.find("Tutu is a young man.\n His student number is 20230001.\0","i") --> 6 x = string.find("Tutu is a young man.\n His student number is 20230001.\0",".") --> 1 x = string.find("Tutu is a young man.\n His student number is 20230001.\0","%a") --> 1 x = string.find("Tutu is a young man.\n His student number is 20230001.\0","%c") --> 21 x = string.find("Tutu is a young man.\n His student number is 20230001.\0","%d") --> 45 x = string.find("Tutu is a young man.\n His student number is 20230001.\0","%l") --> 2 x = string.find("Tutu is a young man.\n His student number is 20230001.\0","%p") --> 20 x = string.find("Tutu is a young man.\n His student number is 20230001.\0","%s") --> 5 x = string.find("Tutu is a young man.\n His student number is 20230001.\0","%u") --> 1 x = string.find("Tutu is a young man.\n His student number is 20230001.\0","%w") --> 1 x = string.find("Tutu is a young man.\n His student number is 20230001.\0","%x") --> 9 x = string.find("Tutu is a young man.\n His student number is 20230001.\0","%z") --> 54
加 ()
表示捕捉,find的第三个参数返回被捕捉到的字符串,在这里即返回找到的那个字符。
x,y,z = string.find("%()~!@#$%^&*():\";\'?<>._[]","(%%)") --> 1 1 % x,y,z = string.find("%()~!@#$%^&*():\";\'?<>._[]","(%#)") --> 7 7 # x,y,z = string.find("%()~!@#$%^&*():\";\'?<>._[]","(%\")") --> 16 16 "
下句中的 +
表示取一个或多个知足条件的连续字符。
--1 2 3 4 5 6 7 8 x,y = string.find("\a\b\f\n\r\t\v\0","%c+") --> 1 7
上句基本列出了全部控制字符,并非全部转义符都是控制字符,例如 \\
和 \xff
不属于控制字符。
match
函数返回符合匹配条件的字符子串。
x = string.match("0123456789ABCDEFabcdefg","%x+") --> 0123456789ABCDEFabcdef
输出的符号即为 %x
所支持的全部字符。
%b
的使用方法与前面的组合形式略有不一样,其形式为 %bxy
,使用示例以下:
---------------------00000000001111111112 22222222233333333334444444444555555 5 ---------------------12345678901234567890 12345678901234567890123456789012345 6 x,y,z = string.find("Tutu is a young man.\n His student number is [20230001].\0","(%b[])") --> 45 54 [20230001] x,y,z = string.find("Tutu is a young man.\n His student number is _20230001_.\0","(%b__)") --> 45 54 _20230001_ x,y,z = string.find("Tutu is a young man.\n His student number is _20230001_.\0","(%b21)") --> 48 53 230001
[]
字符集字符集操做是对字符类中组合的一个扩展。能够经过 []
制定出用户所需的一套字符选取范围。
---------------------0000000001111111111222222222 ---------------------1234567890123456789012345678 x,y,z = string.find("[Email]: tangyikejun@163.com","([123])") --> 22 22 1 x,y,z = string.find("[Email]: tangyikejun@163.com","([l]])") --> 6 7 l] x,y,z = string.find("[Email]: tangyikejun@163.com","([1-3])") --> 22 22 1 x,y,z = string.find("[Email]: tangyikejun@163.com","([^1-3])") --> 1 1 [ x,y,z = string.find("[Email]: tangyikejun@163.com","([^%d])") --> 1 1 [ x,y,z = string.find("[Email]: tangyikejun@163.com","([0-9][%d][%d])") --> 22 24 163 x,y,z = string.find("[Email]: tangyikejun@163.com","([0-9]+)") --> 22 24 163
使用特色:
-
用于限定字符的范围,值域根据字符在ASCII码中对应的值得出,例如 [0-7]
表明字符范围为 0-7。x,y,z = string.find("!\"#$%&0123","([$-1]+)") --> 4 8 $%&01
^
表示对指定的字符范围取补集。[^%d]
等价于 [%D]
。模式项 | 做用 |
---|---|
+ | 匹配1个或多个字符,尽量多地匹配 |
- | 匹配0个或多个字符,尽量少地匹配 |
* | 匹配0个或多个字符,尽量多地匹配 |
? | 匹配0个或1个字符,尽量多地匹配 |
使用特色:
abc-
做用于字符 c
。---------------------0000000001 ---------------------1234567890 x,y,z = string.find("aaaabbbccc","(%a+)") --> 1 10 aaaabbbccc x,y,z = string.find("bbbccc","(a+)") --> nil nil nil x,y,z = string.find("aaaabbbccc","(ab-c)") --> 4 8 abbbc -- x,y,z = string.find("aaaaccc","(ab-c)") --> 4 5 ac -- x,y,z = string.find("aaaaccc","(ab*c)") --> 4 5 ac -- x,y,z = string.find("aaaabccc","(ab?c)") --> 4 6 abc -- x,y,z = string.find("aaaabccc","(ba?c)") --> 5 6 bc
---------------------000000000111 111111122 ---------------------123456789012 345678901 x,y,z = string.find("tangyikejun\0 163.com","(%z%s%w+)") --> 12 16 x,y,z = string.find("tangyikejun\0163.com","(%z%d%w+)") --> nil nil nil
注意: \0
后面不能跟数字。并且用 find 返回的匹配字符串没法输出 \0
以后的部分。
多个模式项组合造成模式。
^
表示匹配从目标字符串的起始位置开始。$
表示匹配目标字符串的末尾子串。^
和 $
做为普通字符处理。---------------------0000000001111111111222222222 ---------------------1234567890123456789012345678 x,y,z = string.find("[Email]: tangyikejun@163.com","^(.%a+)") -->1 6 [Email x,y,z = string.find("[Email]: tangyikejun@163.com","(%a+)$") -->26 28 com
()
捕捉捕捉是指将括号内的组合匹配结果保存起来,每一个括号保存一个结果。
保存的数据的顺序按照左括号的顺序排列。
x,y,z,h,l = string.find("Tutu is a young man.\n His student number is _20230001_.\0","((%a+%s)(%a+%s)%b__)") --> 35 54 number is _20230001_ number is
字符串模式匹配可参考Lua模式匹配。
\0
以后的部分。查找字符串的子串,若是找到,返回子串的起始位置、结束位置;找不到返回 nil。
若是使用捕获(即对模式串用括号包裹起来),则一并返回匹配获得的字符串。
string.find([字符串],[待查找字符串],[查找起始位置]=1,[禁用模式匹配]=false)
只有显式指定了 init 参数才能控制 plain 参数。
x,y,z = string.find("1001 is a Robot", "Robot") print(x,y,z) --> 11 15 nil x,y,z = string.find("1001 is a Robot","1%d",1,true) print(x,y,z) --> nil nil nil x,y,z = string.find("1001 is a Robot","(%d+)",1,false) print(x,y,z) --> 1 2 1001
与 string.find
相似,返回值不同。string.match
查找字符串的子串,若是找到,返回子串;找不到返回 nil。
支持模式匹配。
略
x = string.match("1001 is a Robot","001") print(x) --> 001 x = string.match("1001 is a Robot","%d%d") print(x) --> 10
返回一个迭代函数,该函数每执行一次,就返回下一个捕捉到的匹配(若是没有使用捕捉,就返回整个匹配结果)。
for s in string.gmatch("I have a Dream.","%a+") do print(s) end --> I --> have --> a --> Dream
t = {} s = "name=tangyikejun, number=20250001" -- 将捕获的两个子串分别做为键和值放到表t中 for k, v in string.gmatch(s, "(%w+)=(%w+)") do t[k] = v end -- 输出表t for k,v in pairs(t) do print(k,v) end --> name tangyikejun --> number 20250001
返回格式化以后的字符串。
略
string.format("My name is %s", "tangyikejun") --> My name is tangyikejun
返回字符串长度
返回小写字母的字符串
返回大写字母的字符串
对字符串进行重复
string.rep([字符串],[重复次数])
string.rep("Hello",4) -- HelloHelloHelloHello
返回反转后的字符串。
返回子字符串。
string.sub([字符串],[开始字符下标],[结束字符下标]=-1)
x = string.sub("tangyikejun",7) print(x) --> kejun x = string.sub("tangyikejun",1,-6) print(x) --> tangyi
根据模式匹配对字符串中每个匹配部分都作替换处理,返回替换后的字符串。
string.gsub([字符串],[模式匹配],[替换字符],[最大替换次数] = 无限制)
repl 参数([替换字符]
)支持 字符串、表、函数。
若是 repl 是字符串,那么该字符串就是用于替换的字符串。同时支持 %n
转义符操做,n 的范围是 0-9。n 范围为 [1,9] 时表示第 n 个捕获的匹配字符串,%0
表示整个匹配的字符串,%%
表示替换为一个 %
。
若是 repl 是表,那么将捕获的第一个字符串做为键值(Key)进行查询(没有定义捕捉则以整个匹配的字符串为键值),查到的值做为替换的字符串。
若是 repl 是函数,那么每次匹配成功都会调用该函数,并以按序以全部捕捉做为参数传入函数。没有捕捉则以整个匹配的字符做为参数。
若是从表或函数获得是字符串或者是数字,就将其用于替换;若是获得的是 false 或 nil,那么匹配部分将不会发生变化。
repl 为字符串
s = "Never say die." x = string.gsub(s,"die","never") --> Never say never. x = string.gsub(s,"die","'%0'") --> Never say 'die'. x = string.gsub(s,"(%a+)%s%a+%s(%a+)","%2") --> die.
限制最大替换次数
s = "never say never." x = string.gsub(s,"never","Never",1) --> Never say never.
repl 是表
t = {name="Lua",version="5.1"} x = string.gsub("$name-$version.tar.gz","$(%a+)",t) --> Lua-5.1.tar.gz
repl是函数
x = string.gsub("4+5 = $return 4+5$","%$(.-)%$",function(s)return loadstring(s)() end) --> 4+5 = 9 x = string.gsub("23+45=$result", "((%d+)%+(%d+)=)%$%a+", function (s,a,b) sum = a+b return s..sum end) --> 23+45=68
~~注意:彷佛只支持匿名函数。~~
从表或函数返回的是 false 或 nil
x = string.gsub("4+5 = $return 4+5$","%$(.-)%$",function(s)return nil end) --> 4+5 = $return 4+5$ t = {name="Lua",version=false} x = string.gsub("$name-$version.tar.gz","$(%a+)",t) --> Lua-$version.tar.gz
返回字符的 ASCII 码值。
string.byte([字符串],[起始下标]=1,[结束下标]=[起始下标])
x,y,z = string.byte("abc",2) --> 98 nil nil x,y,z = string.byte("abc",1,3) --> 97 98 99
根据传入的 ASCII 编码值([0-255])获得对应的字符,传入多少编码值就返回多长的字符串。
x = string.char(98,99,100) --> bcd
若是输入字符超限会编译报错。
返回函数的二进制表示(字符串形式),把这个返回值传给 loadingstring 能够得到函数的一份拷贝(传入的函数必须是没有上值的 Lua 函数)。
function sum(a,b) return a + b end s = string.dump(sum) x = loadstring(s)(4,4) -- 8
BNF范式简介 (简要介绍 BNF)
Lua入门系列-果冻想(对Lua进行了较为全面的介绍)
Lua快速入门(介绍 Lua 中最为重要的几个概念,为 C/C++ 程序员准备)
Lua 5.1 中文手册(全面的 Lua5.1 中文手册)
Lua 5.3 中文手册(云风花了6天写的,天哪,我看都要看6天的节奏呀)
Lua迭代器和泛型for(介绍 Lua 迭代器的详细原理以及使用)
How do JavaScript closures work?——StackOverflow(详细介绍了 Javascript 中闭包的概念)
Lua模式匹配(参考了此文中对 %b
的使用)
LuaSocket(LuaSocket 官方手册)
Lua loadfile的用法, 与其余函数的比较(loadfile的介绍部分引用了此文)
Lua 的元表(对元表的描述比较有条理,通俗易懂,本文元表部分参考了此文)
设置函数环境——setfenv(解释了如何方便地设置函数的环境,以及为何要那样设置)
lua5.1中的setfenv使用(介绍了该环境的设置在实际中的一个应用)