Lua语法总结

注释

单行注释

两个减号是单行注释

1
--

多行注释

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

基本数据类型

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

数据类型描述
nil只有值nil属于该类,表示一个无效值
boolean包含两个值:false和true
number表示双精度类型的浮点数
string字符串由一对双引号或单引号来表示
function由 C 或 Lua 编写的函数
userdata表示任意存储在变量中的C数据结构
thread表示执行的独立线路,用于执行协同程序
tableLua 中的表(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)在一个指定的目标字符串中搜索指定的内容,返回其具体位置,不存在则返回 nilstring.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

##

有用就打赏一下作者吧!