Lua语法总结
# 1. 注释
# 1.1 单行注释
两个减号是单行注释
--
# 1.2 多行注释
--[[
多行注释
多行注释
--]]
2
3
4
# 2. 基本数据类型
Lua 中有 8 个基本类型分别为:nil、boolean、number、string、userdata、function、thread和 table。
数据类型 | 描述 |
---|---|
nil | 只有值nil属于该类,表示一个无效值 |
boolean | 包含两个值:false和true |
number | 表示双精度类型的浮点数 |
string | 字符串由一对双引号或单引号来表示 |
function | 由 C 或 Lua 编写的函数 |
userdata | 表示任意存储在变量中的C数据结构 |
thread | 表示执行的独立线路,用于执行协同程序 |
table | Lua 中的表(table)其实是一个"关联数组",数组的索引可以是数字、字符串或表类型。在 Lua 里,table 的创建是通过"构造表达式({})"来完成 |
# 2.1 nil
- nil 类型表示一种没有任何有效值,它只有一个值
nil
- 给全局变量或者 table 表里的变量赋一个 nil 值,等同于把它们删掉
- nil 作比较时应该加上双引号 "
> type(a)
nil
> type(a)==nil
false
> type(a)=='nil'
true
> type(type(a))
string
2
3
4
5
6
7
8
# 2.2 boolean
boolean 类型只有两个可选值:true 和 false,Lua 把false和nil看作是"假",其他的都为"真"。
# 2.3 number
Lua 默认只有一种 number 类型 :double(双精度)类型。
# 2.4 string
字符串由一对双引号或单引号来表示,也可以用 2 个方括号 [[]]
来表示"一块"字符串
> html = [[
>> <html>
>> <head></head>
>> <body>
>> <a href="https://gitlib.com/">Gitlib</a>
>> </body>
>> </html>
>> ]]
> print(html)
2
3
4
5
6
7
8
9
# 2.5 table
- 在 Lua 里,table 的创建是通过"构造表达式"来完成,最简单构造表达式是
{}
。 - Lua 中的表(table)其实是一个"关联数组",数组的索引可以是数字或者是字符串。
- 不同于其他语言的数组把 0 作为数组的初始索引,在 Lua 里表的默认初始索引一般以 1 开始。
# 2.6 function
在 Lua 中,函数是被看作是一种特殊的变量,函数可以存在变量里。
# 2.7 thread
在 Lua 里,最主要的线程是协同程序(coroutine)。它跟线程(thread)差不多,拥有自己独立的栈、局部变量和指令指针,可以跟其他协同程序共享全局变量和其他大部分东西。
线程跟协程的区别:线程可以同时多个运行,而协程任意时刻只能运行一个,并且处于运行状态的协程只有被挂起(suspend)时才会暂停。
# 2.8 userdata
userdata 是一种用户自定义数据,用于表示一种由应用程序或 C/C++ 语言库所创建的类型,可以将任意 C/C++ 的任意数据类型的数据(通常是 struct 和 指针)存储到 Lua 变量中调用。
# 3. 变量
- Lua 中的变量全是全局变量,那怕是语句块或是函数里,除非用
local
显式声明为局部变量。 - 局部变量的作用域为从声明位置开始到所在语句块结束。
- 变量的默认值均为 nil。
- 多个变量可以同时赋值。
> function joke()
>> c = 5 -- 全局变量
>> local d = 6 -- 局部变量
>> end
>
> joke()
> print(c,d)
-- 输出结果,在函数中定义的变量依然是全局变量
5 nil
-- 多个变量赋值
> a, b, c = 0, 1
> print(a,b,c)
0 1 nil
2
3
4
5
6
7
8
9
10
11
12
13
14
# 4. 循环语句
注意
Lua仅支持break跳出循环,不支持continue
# 4.1 while循环
while(condition)
do
statements
end
2
3
4
# 4.2 for循环
-- 数值
for var=min,max,step do
statements
end
-- table进行for循环
a = {"one", "two", "three"}
for i, v in ipairs(a) do
print(i, v)
end
2
3
4
5
6
7
8
9
10
# 4.3 repeat循环
repeat
statements
until(condition)
2
3
# 5. 条件语句
if( 布尔表达式 1)
then
--[ 在布尔表达式 1 为 true 时执行该语句块 --]
elseif( 布尔表达式 2)
then
--[ 在布尔表达式 2 为 true 时执行该语句块 --]
else
--[ 如果以上布尔表达式都不为 true 则执行该语句块 --]
end
2
3
4
5
6
7
8
9
10
# 6. 函数
- Lua函数可以返回多个结果值;
- Lua函数可以接受可变数目的参数,和 C 语言类似,在函数参数列表中使用三点
...
表示函数有可变的参数,通过select("#",...)
来获取可变参数的数量;
function add(...)
local s = 0
for i, v in ipairs{...} do -- {...} 表示一个由所有变长参数构成的数组
s = s + v
end
return s
end
2
3
4
5
6
7
# 7. 字符串操作
方法 | 说明 | 举例 |
---|---|---|
string.upper(str) | 字符串全部转为大写字母 | string.upper("abc") |
string.lower(str) | 字符串全部转为小写字母 | string.lower("abc") |
string.find(str, substr) | 在一个指定的目标字符串中搜索指定的内容,返回其具体位置,不存在则返回 nil | string.find("Hello Lua user", "Lua") |
string.gsub(str,fstr,rstr,num) | 在字符串中替换,num 替换次数(默认为全部替换) | string.gsub("aaaa","a","z",3) |
string.reverse(str) | 字符串反转 | string.reverse("Lua") |
string.format(...) | 类似printf的格式化字符串 | string.format("the value is:%d",4) |
string.len(str) | 计算字符串长度 | string.len("abc") |
.. | 字符串拼接 | str = "ab".."c" |
# 8. 表操作
方法 | 说明 | 举例 |
---|---|---|
table.concat(table,[, sep]) | 将table拼接为字符串,sep参数为分隔符 | table.concat(fruits,", ") |
table.insert(table, [pos,] value) | 在table指定位置插入元素 | table.insert(fruits,2,"grapes") |
table.remove(table [, pos]) | 删除table指定位置元素,并返回该元素,默认删除最后一个元素 | table.remove(fruits) |
table.sort(table [, comp]) | 对给定的table进行升序排序 | table.sort(fruits) |
#table | 获取table长度 | #fruits |
# 9. 模块与包
- Lua的模块是由变量、函数等已知元素组成的table;
- 创建一个模块很简单,就是创建一个 table,然后把需要导出的常量、函数放入其中,最后返回这个 table 就行;
-- 文件名为 module.lua
-- 定义一个名为 module 的模块
module = {}
-- 定义一个常量
module.constant = "这是一个常量"
-- 定义一个函数
function module.func()
io.write("这是一个公有函数!\n")
end
local function func2()
print("这是一个私有函数!")
end
return module
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Lua提供了一个名为require()
的函数用来加载模块,例如:
require("<模块名>")
# 10. 元表
Lua提供了元表(Metatable)来改变table的行为,有点类似于Javascript中的原型链,还为每个行为关联了对应的元方法。例如使用元表,可以定义Lua如何计算两个table的相加操作a+b,当Lua试图对两个表进行相加时,先检查两者之一是否有元表,之后检查是否有一个叫__add
的字段,若找到,则调用对应的值,__add
等字段,其对应的值(往往是一个函数或是table)就是"元方法"。
方法 | 描述 | 举例 |
---|---|---|
setmetatable(table,metatable) | 指定table设置元表 | setmetatable(mytable, mymetatable) |
getmetatable(table) | 返回对象的元表 | getmetatable(mytable) |
__index元方法 | 当你通过键来访问 table 的时候,如果这个键没有值,那么Lua就会寻找该table的metatable中的__index 键 | setmetatable({}, { __index = other }) |
__tostring 元方法 | __tostring 元方法用于修改表的输出行为 |
还有其他各种元方法:
模式 | 描述 |
---|---|
__add | 对应的运算符 '+'. |
__sub | 对应的运算符 '-'. |
__mul | 对应的运算符 '*'. |
__div | 对应的运算符 '/'. |
__mod | 对应的运算符 '%'. |
__unm | 对应的运算符 '-'. |
__concat | 对应的运算符 '..'. |
__eq | 对应的运算符 '=='. |
__lt | 对应的运算符 '<'. |
__le | 对应的运算符 '<='. |
基于元表的特性(继承),可以实现Lua面向对象编程。
# 11. 协程
Lua 协同程序(coroutine)与线程比较类似:拥有独立的堆栈,独立的局部变量,独立的指令指针,同时又与其它协同程序共享全局变量和其它大部分东西。
方法 | 描述 |
---|---|
coroutine.create() | 创建 coroutine,返回 coroutine, 参数是一个函数,当和 resume 配合使用的时候就唤醒函数调用 |
coroutine.resume() | 重启 coroutine,和 create 配合使用 |
coroutine.yield() | 挂起 coroutine,将 coroutine 设置为挂起状态,这个和 resume 配合使用能有很多有用的效果 |
coroutine.status() | 查看 coroutine 的状态 注:coroutine 的状态有三种:dead,suspended,running,具体什么时候有这样的状态请参考下面的程序 |
coroutine.wrap() | 创建 coroutine,返回一个函数,一旦你调用这个函数,就进入 coroutine,和 create 功能重复 |
coroutine.running() | 返回正在跑的 coroutine,一个 coroutine 就是一个线程,当使用running的时候,就是返回一个 corouting 的线程号 |
# 12. 文件I/O
方法 | 说明 | 举例 |
---|---|---|
io.open(filepath, mode) | 打开文件 | file = io.open("test.lua", "r") |
io.input(file) | 设置默认输入文件, file参数为文件句柄 | io.input(file) |
io.output(file) | 设置默认输出文件, file参数为文件句柄 | io.output(file) |
io.read() | 输出文件 | |
io.write(str) | 在文件写入内容 | io.write("文件内容") |
io.close(file) | 关闭打开的文件, file参数为文件句柄 | io.close(file) |
io.lines(filepath) | 返回迭代器,读取文件每一行内容,当到文末,返回nil,并自动关闭文件 | for line in io.lines("main.lua") |
file:read() | 输出文件,file为文件句柄 | |
file:write(str) | 在文件写入内容 | |
file:close() | 关闭打开的文件 |
# 13. 错误处理
# 13.1 assert
assert(type(a) == "number", "a 不是一个数字")
assert首先检查第一个参数,若没问题,assert不做任何事情;否则,assert以第二个参数作为错误信息抛出
# 13.2 error
error (message [, level])
终止正在执行的函数,并返回message的内容作为错误信息
# 13.3 pcall
Lua中处理错误,可以使用函数pcall(protected call)来包装需要执行的代码。
pcall接收一个函数和要传递给后者的参数,并执行,执行结果:有错误、无错误;返回值true或者或false, errorinfo。
if pcall(function_name, ….) then
-- 没有错误
else
-- 一些错误
end
2
3
4
5