Lua 是一门强大、快速、轻量的嵌入式动态类型脚本语言, 使用 ANSI C 语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中, 从而为应用程序提供灵活的扩展和定制功能
数据类型
Lua 有八种基本数据类型: nil、boolean、number、string、function、userdata、thread、table
- nil 表示一个有意义的值不存在时的状态, nil 和 false 逻辑表达式中都表示假, 其他任何值都表示真
- userdata 表示任意存储在变量中的 C 数据, 完全用户数据: 指一块由 Lua 管理的内存对应的对象; 轻量用户数据: 指一个简单的 C 指针
- table 本质是一个关联数组, 数组的索引可以是数字、字符串或表类型, 下标默认从 1 开始, table 可以包含任何类型的值(nil 除外), 任何键的值若为 nil 就不会被记入表内, table 的创建通过
构造表达式 {}
完成
table、function、thread、userdata 在 Lua 中是引用类型, 对其操作都是针对引用而不是针对值的操作
1 | print("数据类型: nil boolean number string userdata function trhead table") |
表
table 其实是关联数组, 可以使用任意类型值(除了 nil)作为数组的索引, 不固定大小
1 | local tb1 = {"banana", "orange", "apple", "grapes"} |
元表
lua 中的每个值都可以有一个元表, 元表就是一个普通的 lua 表, 它用于定义原始值再特定操作下的行为
元表决定了一个对象在数学运算、位运算、比较、连接、取长度、调用、索引时的行为, 元表还可以定义一个函数, 当表对象或用户数据对象在垃圾回收时调用它
元表中的键对应着不同的事件名, 键关联的值被称为 元方法, 通过 getmetatable
方法获取任何值的元表, 通过 setmetatable
方法设置元表
lua 中不能改变 table 以外其他类型的值的元表, 如果需要使用 C API
- __add ‘+’ 操作, 如果任何值不是数值类型(包括不能转换数值的字符串)做加法, lua 就会尝试调用此方法, lua 查找两个操作数是否定义此元方法, 只要有一个操作数包含, 则将两个操作数作为参数传入元方法, 元方法的结果作为这个操作的结果, 如果找不到元方法, 则抛出一个错误
- __sub, ‘-‘ 操作, 行为和
add
操作类似 - __mul, ‘*‘ 操作, 行为和
add
操作类似 - __div, ‘/‘ 操作, 行为和
add
操作类似 - __mod, ‘%’ 操作, 行为和
add
操作类似 - __pow, ‘^’ 幂操作, 行为和
add
操作类似 - __unm, ‘-‘ 取负操作, 行为和
add
操作类似 - __idiv, ‘//‘ 向下取整除法, 行为和
add
操作类似 - __band, ‘&’ 按位与运算, 行为和
add
操作类似, 不同的是 lua 会在任何一个操作数无法转换为整数时尝试取元方法 - __bor, ‘|’ 按位或运算, 行为和
band
操作类似 - __bxor, ‘~’ 按位异或运算, 行为和
band
操作类似 - __bnot, ‘!’ 按位非运算, 行为和
band
操作类似 - __shl, ‘<<’ 左移操作, 行为和
band
操作类似 - __shr, ‘>>’ 右移操作, 行为和
band
操作类似 - __concat, ‘..’ 连接操作, 行为和
add
操作类似, 不同的是 lua 在任何操作数即不是字符串也不是数字(数字总能转换为对应的字符串)的情况下尝试取元方法 - __len, ‘#’ 取长度操作, 如果对象不是字符串, lua 尝试取元方法, 如果有元方法, 则调用并将对象以参数形式传入, 返回值作为结果, 如果对象是一张表且没有元方法, lua 使用表的取长度操作, 其他情况均抛出错误
- __eq, ‘==’ 操作, 行为和
add
操作类似, 不同的是 lua 仅在两个值都是 table 或都是完全用户数据, 且它们不是同一个对象时才尝试取元方法, 调用的结果总是会被转换为布尔值 - __lt, ‘<’ 操作, 行为和
add
操作类似, 不同的是 lua 仅在两个值不全为整数也不全为字符串时才尝试取元方法, 调用的结果总是会被转换为布尔值 - __le, ‘<=’ 操作, 和其他操作不同, 此元方法可能用到两个不同的事件, 首先查找两个操作数的
__le
元方法, 如果找不到则再次查找__lt
元方法, 它会假设 a <= b 等价于 not(b < a), 调用的结果总是会被转换为布尔值
1 | -- metatable.lua |
- __tostring, 元方法用于修改表的输出行为(自定义输出内容)
1 | local mtstringstr = [[ |
- __call, 函数调用操作 func(args), 当 lua 尝试调用一个非函数的值时会尝试取元方法, 如果存在元方法则调用该方法, func 作为第一个参数传入, 原来调用的参数一次排在后面
1 | myTable = {k1 = 1, k2 = 2, 5} |
- __index, table[key] 查找操作, 当 table 不是表或者 table 中不存在 key 这个键时, lua 会尝试取元方法
- 如果 __index 键包含一个 table 时, lua 则会在这个 table 中查找相应的 key
- 如果 __index 键包含一个函数时, lua 则会调用这个函数, table 和 key 作为参数传递给函数并接收函数的返回值作为结果
查找顺序:
- 在 table 中查找, 如果找到则返回该元素, 否则继续
- 判断该 table 是否有元表, 如果没有则返回 nil, 否则继续
- 判断元表是否有 __index 键, 如果没有则返回 nil, 如果 __index 键包含一个 table, 则重复 1. 2. 3, 如果 __index 键包含一个函数, 则返回调用该函数的返回值
1 | print("-------__index是table---------") |
- __newindex, table[key] = value 索引赋值操作, 发生在 table 不是表或者 table 中不存在 key 这个键时, lua 会尝试取元方法
- 如果 __newindex 键包含一个 table 时, lua 则会对这个 table 做索引赋值操作, 索引过程有可能会引发另一次元方法
- 如果 __newindex 键包含一个 函数时, lua 会调用这个函数而不进行赋值操作, table、key、value 将作为函数的参数传入
1 | print("-------__newindex是table---------") |
- __gc, 垃圾收集元方法, 当垃圾收集循环时触发
1 | -- metatable.lua |
弱表
弱表指内部元素为 弱引用
的表, 垃圾收集器会忽略弱引用计数, 如果一个对象只被弱引用引用时, 垃圾收集器就会回收这个对象
一张弱表可以有弱键或者弱值, 也可以键值都是弱引用, 仅包含弱键的表允许垃圾收集器回收它的键, 但会阻止对值所指的对象回收, 若一张表的键值均为弱引用, 那么收集器可以回收其中的任意键和值
在任何情况下, 只要键或值的任意一项被回收, 相关联的键值对都会从表中移除
一张表的元表中的 __mode 域控制着这张表的弱属性
- 当 __mode 域是一个包含字符 k 的字符串时, 这张表的所有键都为弱引用
- 当 __mode 域是一个包含字符 v 的字符串时, 这张表的所有值都为弱引用
属性为 弱键强值
的表也被称为 暂时表
, 对于一张暂时表, 它的值是否可达仅取决于其对应键是否可达
对一张表的弱属性的修改仅在下次手机循环才生效, 只有那些有显式构造过程的对象才会从弱表中移除, 值, 例如数字和轻量 C 函数, 不受垃圾收集器管辖, 因此不会从弱表中移除(除非它们的关联项被回收)
协程
lua 支持协程(协同式多线程), 一个协程在 lua 中代表了一段独立的执行线程, 协程拥有独立的堆栈, 独立的局部变量, 同时又与其他协程共享全局变量和其他大部分东西,
协程和线程的主要区别:
一个具有多个线程的程序可以同时运行多个线程, 协程却需要彼此协作的运行, 在任一指定时刻只有一个协程在运行, 并且这个正在运行的协程只有在明确的被要求挂起时才会被挂起
协程的运行可能被两种方式终止, 正常途径是主函数返回(显式返回或者执行完最后一条指令), 非正常途径是发生了一个未捕获的错误, 对于正常结束, coroutine.resume()
将返回 true 和协程主函数的返回值, 当错误发生时, coroutine.resume()
将返回 false 和错误信息
- coroutine.create(func) 创建 coroutine 并返回协程句柄, 当和 resume 配合使用时就唤醒函数调用
- coroutine.resume(co [, val1, …]) 重启 coroutine 并将参数传入, 协程正常运行返回 true 和 传给 yield 的所有值(当协程让出)或者主体函数的所有返回值(当协程中止), 有错误发生时返回 false 和错误信息
- coroutine.isyieldable() 判断正在运行的协程是否可以让出, 可以返回 1, 否则返回 0
- coroutine.yield(args) 挂起 coroutine, 如果有参数则将参数返回给调用线程
- coroutine.status(co) 查看 coroutine 的状态, 通常返回 dead, suspended, running
- coroutine.wrap(f) 创建 coroutine 并返回一个函数, 启动协程需要手动调用这个函数
- coroutine.running() 返回当前正在运行的 coroutine 和一个布尔值, 如果当前运行的协程是主线程, 布尔值为 true, 否则为 false
1 | -- coroutine.lua |
1 | -- coroutine.lua |
生产者与消费者
1 | local newProducer |
词法约定
关键字
and break do else elseif end false for function goto if in local nil not or repeat return then true until while
字符串
1 | --这是单行注释, 不会被执行 |
1 | a = 'alo\n123"' -- 字符串中包含另一种字符串的引号不需要转义 |
变量
Lua 有三种变量: 全局变量, 局部变量和表的域
所有没有显式声明的局部变量名都被当做全局变量, 在变量的首次赋值之前, 默认值都为 nil
变量的作用范围开始于声明它们之后的第一个语句段
1 | x = 10 -- 全局变量 |
控制结构
- if, if exp then block {elseif exp then block} [else block] end
- while, while exp do block end
- for, for exp do block end
- repeat, repeat block until exp
运算符
- 算术运算符: + - * / // % ^ -
- 关系运算符: == ~= < <= > >=
- 逻辑运算符: and or not
- 位运算符: & | ~ << >>
- 字符串拼接: ..
- 取长度操作符(元方法__len): #
函数定义
- 冒号语法可以用来定义方法, 使函数有一个隐形的形参 self, 代表函数自己
1 | print("面向对象: lua 使用 table 描述对象的属性, 使用 function 描述方法, 使用 table + function 模拟面向对象") |
C API 中的函数和类型
- lua_status(lua_State *L) 返回线程 L 的状态, 正常状态为 0(LUA_OK), 当线程用 lua_resume 执行完毕并抛出了一个错误时, 状态值时错误码, 如果线程被挂起, 状态为 LUA_YIELD
- lua_version(lua_State *L) 返回在 Lua 内核中保存的版本数字的地址
辅助库
辅助库提供了一些便捷函数, 方便在 C 中为 Lua 编程, 基础 API 提供了 C 和 Lua 交互用的主要函数, 而辅助库则为一些常见的任务提供了高阶函数
所有辅助库中的函数和类型都定义在头文件 lauxlib.h 中, 它们均带有前缀 luaL_
辅助库中的所有的函数都基于基础 API 实现
一些辅助库函数会在内部使用一些额外的栈空间, 当辅助库使用的栈空间少于 5 个时, 它们不会取检查栈大小, 而是简单的假设栈够用
一些辅助库看中的函数用于检查 C 函数的参数, 因为错误信息格式化为指代参数
函数和类型
- luaL_addchar(luaL_Buffer *B, char c) 向缓存 B 添加一个字节 c
- luaL_addlstring(luaL_Buffer *B, const char *s, size_t l) 向缓存 B 添加一个长度为 l 的字符串 s, 这个字符串可以包含零
- luaL_addstring(luaL_Buffer *B, const char *s) 向緩存 B 添加一个零结尾的字符串 s
- luaL_callmeta(lua_State *L, int obj, const char *e) 调用一个元方法, 如果在索引 obj 处的对象有元表, 且元表有域 e, 这个函数会以该对象为参数调用这个域, 这种情况下, 函数返回真并将调用返回值压栈, 如果这个位置没有元表, 或没有对应的元方法, 此函数返回假(并不会将任何东西压栈)
- luaL_dostring(lua_State *L, const char *str) 加载并运行指定的字符串(使用 luaL_loadstring 或者 luaL_pcall 定义), 如果没有错误返回假, 有错误返回真
- luaL_getmetatable(lua_State *L, const char *tname) 将注册表中 tname 对应的元表压栈, 如果没有 tname 对应的元表, 则将 nil 压栈并返回假
- luaL_len(lua_State *L, int index) 以数字形式返回给定索引处值的 长度, 等价于在 lua 中使用 # 的操作, 如果结果不是一个整数, 则抛出一个错误
- luaL_loadstring(lua_State *L, const char *s) 将一个字符串加载为 lua 代码块, 这个函数使用 lua_load 加载一个零结尾的字符串 s, 返回值和 lua_load 相同
标准库
标准库提供了一些有用的函数, 它们都是直接用 C API 实现的, 其中一些函数提供了原本语言就有的服务(type/getmetatable), 另一些提供和 外部
打交道的服务(I/O)
还有些本可以用 lua 本身来实现, 但在 C 中实现可以满足关键点上的性能需求(例如 table.sort)
所有的库都是直接用 C API 实现的, 并以分离的 C 模块形式提供
基础库
- assert(v[,message]) 如果参数 v 的值为假(nil 或 false)就会调用 error, message 为错误对象, 否则返回所有的参数
- error (message [, level]) 终止正在执行的函数, 并返回 message 的内容作为错误信息, level 指示获取错误的位置: 1 默认, 为调用 error 的位置(文件+行), 2 指出调用 error 函数的函数, 0 不添加错误位置信息
- pcall(f [, arg1, …]) 传入参数, 以保护模式调用函数 f
1 | print("错误: 语法错误 和 运行时错误") |
- collectgarbage ([opt [, arg]]) 垃圾收集器的通用接口, opt 提供了一组不同的功能
1 | print("垃圾回收: lua 采用了自动内存管理, collectgarbage([opt] [, arg])") |
- getmetatable(object) 返回 object 的元表, 如果不包含元表则返回 nil
- ipairs(t) 返回 3 个值(迭代函数, 表 t, 以及 0)
- pairs(t) 如果 t 有元方法 __pairs, 以 t 为参数调用它并返回其返回的前 3 个值,否则, 返回 3 个值(迭代函数, 表 t, 以及 nil)
1 | for i,v in ipairs(t) do -- 将迭代键值对(1, t[1]), (2, t[2]) ... 知道第一个空值 |
- print(…) 接收任意数量的参数, 并将它们的值打印到 stdout
- rawequal(v1, v2) 在不触发任何元方法的情况检查 v1 和 v2 是否相等, 返回一个布尔值
- rawlen(v) 在不触任何元方法的情况下返回对象 v 的长度
- rawset(table, index, value) 在不触发任何元方法的情况将 table[index] 设置为 value, table 必须是一张表
- tonumber(e [, base]) 尝试将 e 转换为一个指定 base 进制的数字
- tostring(v) 将参数 v 转换为可阅读的字符串形式
- type(v) 返回指定参数的类型编码的字符串形式
协程库
包管理库
模块: 封装公用的代码以 API 接口的形式在其他地方调用, 简单理解是将变量、常量、函数放在一个 table 里面,然后 return 返回
使用 require 方法加载模块, require("模块名") 或者 require "模块名"
模块的加载机制: require 用于搜索 lua 文件的路径是存放在全局变量 package.path 中, 当 lua 启动后, 会以环境变量 LUA_PATH 的值来初始这个环境变量, 如果没有找到该环境变量, 则使用一个编译时定义的默认路径来初始化, 此环境变量也可以自定义设置, 在搜索过程中, 如果找到该文件, 则使用 pacakge.loadfile 来加载模块, 否则就去找 C 程序库, 搜索的文件路径是从全局变量 package.cpath 获取, 而这个变量则是通过环境变量 LUA_CPATH 来初始, 此时搜索的文件是 so 或 dll 类型的文件, 如果找到了则使用 package.loadlib 来加载
- require(modename) 加载一个模块
- package.config 描述一些为包管理准备的编译期配置信息的串
- package.cpath 模块在 C 加载器中加载时的搜索路径
- package.loaded 控制哪些模块已经被加载的表
- package.loadlib(libname, funcname)
- package.path 模块在 lua 加载器中加载时搜索路径
- package.preload 保存一些特殊模块的加载器
- package.searchers 控制如何加载模块的表
- package.searchpath(name, path [, sep [, rep]]) 在指定 path 中搜索指定的 name
1 | local modulestr = [[ |
字符串控制
这个库提供了字符串处理的通用函数
- string.upper 转换大写”, string.upper(“AbCdE”))
- string.lower 转换小写”, string.lower(“AbCdE”))
- string.gsub 字符串查找替换”, string.gsub(“hello world”, “l”, ‘r’))
- string.find 查找子串位置”, string.find(“hello lua user”, “lua”))
- string.reverse 字符串反转”, string.reverse(“hello world”))
- string.format 根据字符串模板返回格式化的字符串”, string.format(“the value is %d”, 4))
- string.char 返回数值表示的字符, byte 返回字符的数值表示”, string.char(96, 99, 100), string.byte(‘ABCD’))
- string.len 返回字符串的长度”, string.len(“abc”))
- string.rep 返回字符串的 n 个拷贝”, string.rep(“abc”, 3))
- string.gmatch 返回一个迭代器函数, 每次调用函数返回一个字符串中找到的下一个符合 pattern 模式的子串, 可以结合 for 循环查找”)
- string.match 返回在字符串中查找符合匹配模式的第一个子串”)
- string.sub 截取字符串”, string.sub(‘hello world’, 1, 6))
基础 UTF-8 支持
这个库提供了怼 UTF-8 编码的基础支持, 所有的函数都放在表 utf8 中, 此库不提供除编码处理之外的任何 unicode 支持
- utf8.char(…) 接收零个或多个整数, 将每个整数转换成对应的 UTF-8 字节序列, 并返回这些序列连接到一起的字符串
- utf8.codes(s) 返回一系列的值, 迭代出字符串 s 中所有的字符
- utf8.codepoint(s [, i [, j]]) 以整数形式返回 s 中从位置 i 到 j 间(包括两端啊)所有字符的编码, 默认 i 为 1, j 为 i
- uft8.len(s [, i [, j]]) 返回字符串 s 中从位置 i 到 j 间(包含两端) UTF-8 字符的个数, 默认 i 为 1, j 为 -1
- uft8.offset(s, n [, i]) 返回编码在 s 中的第 n 个字符的开始位置(按字节数)(从位置 i 开始统计), 如果指定的字符不在其中或在结束点之后, 函数返回 nil
表控制
- table.insert(list, [pos, ] value) 在 list 的位置 pos 处插入元素 value, 并向后移动元素, table.insert(tb1, 3, “hello world”)
- table.pack(…) 返回用所有参数乘以键 1, 2, 等填充的新表, 并将 n 这个域设为参数的总数
- table.remove(list [, pos]) 移除 list 中 pos 位置的元素并返回移除的元素, pos 默认为 #list, table.remove(tb2, 2)
- table.sort(list [, comp]]) 对 list 进行排序, 如果提供了参数 comp, 则 comp 必须是一个可以接收两个列表内元素为参数的函数, table.sort(tb1)
- table.unpack(list [, i [, j]]) 返回 list 中的元素, 默认 i 为 1, j 为 #list
- table.concat 列出表中指定区间的所有元素, table.concat({“hello”, “world”, “lua”, 2022}, “-“)
数学函数
这个库提供了基本的数学函数, 所有函数都放在表 math 中, 注解有 integer/float 的函数会对整数参数返回整数结果, 对浮点(或混合)参数返回浮点结果, 圆整函数(math.ceil, math.floor, math.modf)的结果在整数范围内是返回整数, 否则返回浮点数
输入输出
I/O 库提供了两套不同风格的文件处理接口
- 简单模式(simple mode), 它提供设置默认输入文件及默认输出文件的操作, 所有的输入输出操作都针对这些默认文件
- 完全模式(complete mode), 当使用隐式文件句柄时, 所有的操作都是由表 io 提供, 若使用显式文件句柄, io.open 会返回一个文件句柄, 且所有的操作都由该文件句柄的方法来提供
表 io 中也提供了三个和 C 中含义相同的预定义文件句柄: io.stdin, io.stdout, 以及 io.stderr, I/O 库永远不会关闭这些文件
io.close([file]) 等价于 file:close(), 不指定 file 时关闭默认输出文件
io.flush() 等价于 io.output():flush()
io.input([file]) 当文件名调用它时, (以文本模式)来打开该名字的文件, 并将文件句柄设为默认输入文件, 如果用文件句柄调用它时, 就简单的将该句柄设为默认输入文件, 如果调用时不传参数, 则返回当前的默认输入文件
io.lines([filename …]) 以读模式打开指定的文件名并返回一个迭代函数, 此迭代函数的工作方式和用一个已打开的文件去调用 file:lines(…) 得到的迭代器相同, 当迭代函数检测到文件结束, 它不返回值(让循环结束)并自动关闭文件
调用 io.lines() (不传文件名) 等价于 io.input():lines(‘*|’), 按行迭代标准输入文件, 在此情况下, 循环结束后它不会关闭文件
io.open(filename [, mode]) 用字符串 mode 指定的模式打开一个文件并返回新的文件句柄, 当出错时, 返回 nil 和错误信息
- r 读模式, 默认
- w 写模式
- a 追加模式
- r+ 更新模式, 所有之前的数据都保留
- w+ 更新模式, 所有之前的数据都删除
- a+ 追加更新模式, 所有之前的数据都保留, 只允许在文件尾部写入
io.output([file]) 类似于 io.input(), 不过都针对默认输出文件操作
io.popen(prog [, mode]) 跟系统有关, 不是所有平台都提供, 用一个分离进程开启程序 prog, 返回的文件句柄可用于从这个程序中读取数据
io.read(…) 等价于 io.input():read(…)
io.tmpfile() 返回一个临时文件的句柄, 这个文件以更新模式打开, 在程序结束时自动删除
io.type(obj) 检查 obj 是否是合法的文件句柄, 如果是返回 ‘file’, 如果是关闭的文件句柄返回 ‘closed file’, 不是则返回 nil
io.write(…) 等价于 io.output():write(…)
file:close() 关闭文件
file:flush() 将写入的数据保存到 file 中
file:lines(…) 返回一个迭代器函数, 每次调用迭代器时, 都从文件中按指定格式读取数据, 默认 ‘|’
file:read(…) 按照指定格式读取文件, 默认读取一行
- *|l 默认, 从当前位置开始读取一行, 遇到文件末尾(EOF)返回 nil
- *L 读取一行并保留行结束标记(如果有的话), 当在文件末尾时,返回 nil
- *n 从当前位置读取数字直到行尾或者非数字字符结束并返回结果, 否则返回 nil
- *i 读取一个整数并返回
- *a 从当前位置开始读取所有内容
- number 从当前位置读取指定数量 number 个字符并返回
file:seek([where [, offset]]) 设置及获取当前文件的位置
- cur 从当前位置开始, 默认
- set 从文件头开始
- end 从文件尾开始
- offset 默认 0, 偏移量
file:setvbuf(mode [, size]) 设置文件的缓冲模式
- no 不缓冲, 输出操作立刻生效
- full 完全缓冲, 只有在缓存满或当显式的对文件调用 flush 时才真正做输出操作
- line 行缓冲, 缓冲有效将到每次换行前, 对于某些特殊文件(例如终端设备)缓冲到任何输入前
- size 以字节为单位指定缓冲区大小
file:write(…) 将参数的值逐个写入 file, 参数必须是字符串或数字, 成功返回 file, 否则返回 nil 和错误信息
1 | print("文件 I/O: 用于读取和处理文件") |
操作系统库
- os.clock() 返回程序使用的按秒计 CPU 时间的近似值
- os.date([format [, time]]) 返回一个包含日期及时刻的字符串或表, 格式化方法取决于所给字符串 format
- os.difftime(t2, t1) 返回以秒计算的时刻 t1 到 t2 的差值
- os.execute([command]) 调用系统解释器执行 command, 执行成功返回 true, 否则返回 nil, 在第一个返回值之后, 函数返回一个字符串加一个数字
- exit 命令正常结束, 接下来的数字是命令的退出状态码
- signal 命令被信号打断, 接下来的数字是打断该命令的信号
- os.exit([code [, close]]) 终止宿主程序, 如果 close 为真, 在退出前关闭 lua 状态机
- 如果 code 为 true, 返回的状态码是 EXIT_SUCCESS
- 如果 code 为 false, 返回的状态码是 EXIT_FAILURE
- 如果 code 是一个数字, 返回的状态码就是这个数字, code 默认值为 true
- os.getenv(varname) 返回进程环境变量 varname 的值, 如果未定义则返回 nil
- os.remove(filename) 删除指定的文件, 如果函数失败则返回 nil 和错误信息
- os.rename(oldname, newname) 重命名文件, 如果函数失败则返回 nil 和错误信息
- os.setlocale(locale [, category]) 设置程序的当前区域, locale 是一个区域设置的系统相关字符串, category 是一个描述由改变哪个分类的可选字符串: all, collate, ctype, monetary, numeric, time, 默认为 all
- os.time([table]) 当不传参数时, 返回当前时刻, 如果传入一张表则返回由这张表表示的时刻, 这张表必须包含域 year, month, day, 可以包含 hour(默认为 12), min(默认为 0), sec(默认为 0), 以及 isdst(默认为 nil)
- os.tmpname() 返回一个可用于临时文件的文件名字符串, 这个文件在使用前必须显式打开, 不再使用时需要显式删除
调试库
lua 提供了 debug 库用于提供创建自定义调试器的功能
- debug.debug() 进入一个用户交互模式,运行用户输入的每个字符串, 使用简单命令以及其他调试设置, 用户可以检阅全局变量和局部变量, 改变变量的值, 计算一些表达式等等, 输入一行仅包含 count 的字符串将结束这个函数继续向下运行
- debug.gethook([thread]) 返回三个表示线程钩子设置的值: 当前钩子函数, 当前钩子掩码, 当前钩子计数
- debug.getinfo([thread,] f [, what]) 返回一个关于函数信息的表, 也可以提供一个数字 f 表示的函数, 数字 f 表示运行在指定线程的调用栈对应层次上的函数, 0 层表示当前函数(getinfo 自身), 1 层表示调用 getinfo 的函数
- debug.getlocal([thread, ] f, local) 返回在栈的 f 层处函数的索引为 local 的局部变量的名字和值, 此函数不仅用于访问显式定义的局部变量, 还包括形参, 临时变量等
- debug.getmetatable(value) 返回给定 value 的元表, 如果没有则返回 nil
- debug.getregistry() 返回注册表表, 这是一个预定以的表, 可以用来保存任何 C 代码想保存的 lua 值
- debug.getupvalue(f, up) 返回函数 f 的第 up 个上值的名字和值, 如果没有则返回 nil
- debug.getuservalue(u) 返回关联在 u 上的 lua 值, 如果 u 并非用户数据, 返回 nil
- debug.sethook([thread,] hook, mask [, count]) 将一个函数作为钩子函数设入, 字符串 mask 以及数字 count 决定了钩子将在何时调用, mask: c 每当 lua 调用一个函数, 调用此钩子, r 每当 lua 从一个函数内返回时, 调用钩子, l 每当 lua 进入新的一行时, 调用钩子
- debug.setlocal([thread, ] level, local, value) 将 value 赋值给栈上第 level 层函数的第 local 个局部变量, 如果没有那个变量返回 nil, 如果 level 越界则抛出一个错误
- debug.setmetatable(value, table) 将 value 的元表设置为 table(可以是 nil), 返回 value
- debug.setupvalue(f, up, value) 将 value 设置为函数 f 第 up 个上值, 如果函数没有那个上值返回 nil, 否则返回 up 上值的名字
- debug.setuservalue(udata, value) 将 value 设置为 udata 的关联值, udata 必须是一个完全用户数据, 返回 udata
- debug.traceback([thread,] [message [, level]]) 追踪堆栈信息, message 被添加到栈回朔信息的头部, level 指定从栈的哪一层开始回朔(默认: 1)
- debug.upvalueid(f, n) 返回指定函数第 n 个上值的唯一标识符(一个轻量用户数据), 这个唯一标识符可以让程序检查两个不同的闭包是否共享了上值, 如果是则返回相同的标识符
- debug.upvaluejoin(f1, n1, f2, n2) 让 lua 闭包 f1 的第 n1 个值引用 lua 闭包 f2 的第 n2 个值
其他语法
1 | #!/usr/local/bin/lua |
包管理工具
LuaRocks 是一个 Lua 包管理器,基于 Lua 语言开发,提供一个命令行的方式来管理 Lua 包依赖、安装第三方 Lua 包等,社区比较流行的包管理器之一
安装
1 | [root@centos7 workspace]# wget https://luarocks.org/releases/luarocks-3.9.2.tar.gz |
常用命令
- --help 查看命令帮助信息
- show <rock> 显示指定包的详细信息
- doc <rock> 查看指定包的文档
- search <rock> 查找服务器中的指定包
- list 列出所有安装的包
- install <rock> 安装指定的包
- --check-lua-versions 检查包的兼容性
- remove <rock> 移除指定的包
- purge 移除所有的包
- path 显示当前配置的包的目录
- build 编译安装当前目录的 rock
- make 在当前目录中使用 rockspec 文件编译安装 rock
- pack 在当前目录下创建一个 rock
- unpack <rock> 解包一个 rock
- upload <rockspec> 创建一个 rock 并上传到公共服务器
连接 redis
1 | local redis = require "redis" |