Lua语法总结

注释

单行注释

两个减号是单行注释

1
--

多行注释

1
2
3
4
--[[
多行注释
多行注释
--]]

基本数据类型

Lua 中有 8 个基本类型分别为:nilbooleannumberstringuserdatafunctionthreadtable

数据类型 描述
nil 只有值nil属于该类,表示一个无效值
boolean 包含两个值:false和true
number 表示双精度类型的浮点数
string 字符串由一对双引号或单引号来表示
function 由 C 或 Lua 编写的函数
userdata 表示任意存储在变量中的C数据结构
thread 表示执行的独立线路,用于执行协同程序
table Lua 中的表(table)其实是一个”关联数组”,数组的索引可以是数字、字符串或表类型。在 Lua 里,table 的创建是通过”构造表达式({})”来完成

nil

  • nil 类型表示一种没有任何有效值,它只有一个值 nil
  • 给全局变量或者 table 表里的变量赋一个 nil 值,等同于把它们删掉
  • nil 作比较时应该加上双引号 “
1
2
3
4
5
6
7
8
> type(a)
nil
> type(a)==nil
false
> type(a)=='nil'
true
> type(type(a))
string

boolean

boolean 类型只有两个可选值:true和 false,Lua 把falsenil看作是”假”,其他的都为”真”。

number

Lua 默认只有一种 number 类型 :double(双精度)类型。

string

字符串由一对双引号或单引号来表示,也可以用 2 个方括号 “[[]]” 来表示”一块”字符串

1
2
3
4
5
6
7
8
9
> html = [[
>> <html>
>> <head></head>
>> <body>
>> <a href="https://gitlib.com/">Gitlib</a>
>> </body>
>> </html>
>> ]]
> print(html)

table

  • 在 Lua 里,table 的创建是通过”构造表达式”来完成,最简单构造表达式是{}。
  • Lua 中的表(table)其实是一个”关联数组”,数组的索引可以是数字或者是字符串。
  • 不同于其他语言的数组把 0 作为数组的初始索引,在 Lua 里表的默认初始索引一般以 1 开始

function

在 Lua 中,函数是被看作是一种特殊的变量,函数可以存在变量里。

thread

在 Lua 里,最主要的线程是协同程序(coroutine)。它跟线程(thread)差不多,拥有自己独立的局部变量指令指针,可以跟其他协同程序共享全局变量和其他大部分东西。

线程跟协程的区别:线程可以同时多个运行,而协程任意时刻只能运行一个,并且处于运行状态的协程只有被挂起(suspend)时才会暂停。

userdata

userdata 是一种用户自定义数据,用于表示一种由应用程序或 C/C++ 语言库所创建的类型,可以将任意 C/C++ 的任意数据类型的数据(通常是 struct 和 指针)存储到 Lua 变量中调用。

变量

  • Lua 中的变量全是全局变量那怕是语句块或是函数里,除非用 local 显式声明为局部变量。

  • 局部变量的作用域为从声明位置开始到所在语句块结束。

  • 变量的默认值均为 nil。

  • 多个变量可以同时赋值。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    > 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

循环语句

注意:Lua仅支持break跳出循环,不支持continue;

while循环

1
2
3
4
while(condition)
do
statements
end

for循环

1
2
3
4
5
6
7
8
9
10
-- 数值
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

repeat循环

1
2
3
repeat
statements
until( condition

条件语句

1
2
3
4
5
6
7
8
9
10
if( 布尔表达式 1)
then
--[ 在布尔表达式 1 为 true 时执行该语句块 --]

elseif( 布尔表达式 2)
then
--[ 在布尔表达式 2 为 true 时执行该语句块 --]
else
--[ 如果以上布尔表达式都不为 true 则执行该语句块 --]
end

函数

  • Lua函数可以返回多个结果值;
  • Lua函数可以接受可变数目的参数,和 C 语言类似,在函数参数列表中使用三点...表示函数有可变的参数,通过select("#",...)来获取可变参数的数量;
1
2
3
4
5
6
7
function add(...)  
local s = 0
for i, v in ipairs{...} do -- {...} 表示一个由所有变长参数构成的数组
s = s + v
end
return s
end

字符串操作

方法 说明 举例
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”

表操作

方法 说明 举例
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

模块与包

  • Lua的模块是由变量、函数等已知元素组成的table;
  • 创建一个模块很简单,就是创建一个 table,然后把需要导出的常量、函数放入其中,最后返回这个 table 就行;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-- 文件名为 module.lua
-- 定义一个名为 module 的模块
module = {}

-- 定义一个常量
module.constant = "这是一个常量"

-- 定义一个函数
function module.func()
io.write("这是一个公有函数!\n")
end

local function func2()
print("这是一个私有函数!")
end

return module

Lua提供了一个名为require()的函数用来加载模块,例如:

1
require("<模块名>")

元表

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面向对象编程。

协程

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 的线程号
1
2


文件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() 关闭打开的文件

错误处理

assert

1
assert(type(a) == "number", "a 不是一个数字")

assert首先检查第一个参数,若没问题,assert不做任何事情;否则,assert以第二个参数作为错误信息抛出

error

1
error (message [, level])

终止正在执行的函数,并返回message的内容作为错误信息

pcall

Lua中处理错误,可以使用函数pcall(protected call)来包装需要执行的代码。

pcall接收一个函数和要传递给后者的参数,并执行,执行结果:有错误、无错误;返回值true或者或false, errorinfo。

1
2
3
4
5
if pcall(function_name, ….) then
-- 没有错误
else
-- 一些错误
end

##

有用就打赏一下作者吧!