基本约定
脚本:要以xxx.lua命名,不用";"结尾,但是每一个语句要一行。
注释:单行–,多行–[[ ]]–
变量:不用声明(默认都是nil),可以直接赋值才会有类型。但是可以声明为local局部变量(默认为全局变量)
赋值:可以多个变量进行赋值,多则省去,少则nil补,而且赋值语句是先进行右边的才进行左边赋值,即交换两个变量直接 x,y=y,x
循环:1.for var=exp1,exp2,exp3 do \n <执行体> \n end ( var 从 exp1 变化到 exp2,每次变化以 exp3 为步长递增 var)。2.while(conditon) \n do \n <执行体> \n end 3.repeat \n <执行体>\n until(conditon)
流程:if(condition)\n then \n <执行体> \n end
函数:function Name(parameter ···) \n function_body \n return values \n end(可以返回多个值)
符号
运算符号:比较特别的是"^"(乘幂),其他都是四则运算那些。
其他符号:"…“用来连接两个字符串。”#"求一个字符串长度。
字符串
格式化:%c - 接受一个数字, 并将其转化为ASCII码表中对应的字符;%d - 接受一个数字并将其转化为有符号的整数格式;%f - 接受一个数字并将其转化为浮点数格式;
宽度数值和保留位数: %+一个浮点数,宽度数值为整数部分,保留位数为小数部分, 如浮点数转义符,%6.3f则设定该浮点数的占宽度数为6,浮点数小数只保留3位。
对齐标识: 在指定了字串宽度时, 默认为右对齐, 增加-号可以改为左对齐.
匹配模式
用于模式匹配函数 string.find, string.gmatch, string.gsub, string.match。
.(点): 与任何字符配对;%a: 与任何字母配对;%c: 与任何控制符配对(例如\n);%d: 与任何数字配对;%l: 与任何小写字母配对;%p: 与任何标点(punctuation)配对;%s: 与空白字符配对;%u: 与任何大写字母配对;%w: 与任何字母/数字配对。(若大写字母则与原来相反效果, 例如, %A表示与任何非字母字符配对)
[多个字符]:与任何[]中包含的字符类配对.。例如[%w_]与任何字母/数字, 或下划线符号”_“配对。 [^多个字符]: 与任何不包含在[]中的字符类配对。
‘%’ 用作特殊字符的转义字符,因此 ‘%.’ 匹配点;’%%’ 匹配字符 ‘%’。转义字符 '%'不仅可以用来转义特殊字符,还可以用于所有的非字母的字符。
模式条目:单个字符类跟一个 '’, ‘-’ 都是将匹配零或多个该类的字符。不同的是’'匹配尽可能长的串,而 '-'匹配尽可能短的串;单个字符类跟一个 ‘+’, 将匹配一或更多个该类的字符。 这个条目总是匹配尽可能长的串; 单个字符类跟一个 ‘?’, 将匹配零或一个该类的字符。 只要有可能,它会匹配一个;
%bxy, 这里的 x 和 y 是两个明确的字符; 这个条目匹配以 x 开始 y 结束, 且其中 x 和 y 匹配是一对的。 意思是,如果从左到右读这个字符串,对每次读到一个 x 就 +1 ,读到一个 y 就 -1, 最终结束处的那个 y 记数为 0。 举个例子,条目 %b()可以匹配到括号平衡的表达式。
捕获
模式可以在内部用小括号括起一个子模式;这些子模式被称为捕获物。 其实就是根据一个模式从目标字符串中抽出匹配于该模式的内容。在指定捕获时,应将模式中需要捕获的部分写到一对圆括号中。如:string.match( “score = 120”, “(%a+)%s*=%s*(%d+)”) 那么%a+匹配到的就存放在1号捕获物里,%d+匹配到的就存放在2号捕获物里。
%n, 这里的 n 可以从 1 到 9; 这个条目匹配一个等于 n 号捕获物的子串。
数组
在 Lua 数组索引值默认是以 1 为起始。但是赋值的时候索引可以自己规定,如:
array = {10}
print(array[1])
for i= -2, 2 do
array[i] = i
end
for i = -2,2 do
print(array[i])
end
1
2
3
4
5
6
7
8
那么一开始array[1]为10,后面输出为-2,-1,0,1,2;
表
表是 Lua 的一种数据结构用来帮助我们创建不同的数据类型,如:数组、字典等。但是表的索引是可以用其他任何值来规定的。如:mytable = {"key1"=val1,1}那么mytable[1]的值为1,mytable[“key1”]的值就为val1;
原表
元表(Metatable)允许我们改变table的行为,每个行为关联了对应的元方法。
Lua查找一个表元素时的规则,其实就是如下3个步骤:
在表中查找,如果找到,返回该元素,找不到则继续
判断该表是否有元表,如果没有元表,返回nil,有元表则继续。
判断元表有没有__index方法,如果__index方法为nil,则返回nil;如果__index方法是一个表,则重复1、2、3;如果__index方法是一个函数,则返回该函数的返回值。
__index 元方法用来对表访问 。
__newindex 元方法用来对表更新 ,对新索引键(newkey)赋值时是对含此键的表赋值(类似C#的Set)。
__call 元方法在 Lua 调用一个值时调用(类似C#的Get)。
__tostring 元方法用于修改表的输出行为
迭代器
——“迭代器”就是一种可以遍历一种集合中所有元素的机制。
泛型 for 迭代器:泛型 for 在自己内部保存迭代函数,实际上它保存三个值:迭代函数、状态常量、控制变量。如:
local table =
{
[1] = "test1",
[2] = "test2",
[4] = "test4",
[5] = "test5"
}
for i,v in pairs(table) do -- 输出 "test1" "test2" "test4" "test5"
print( table[i] )
end
for i,v in ipairs(table) do -- 输出 "test1" "test2" k=3时断开
print( table[i] )
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
无状态的迭代器:迭代函数都是用两个变量(状态常量和控制变量)的值作为参数被调用,一个无状态的迭代器只利用这两个值可以获取下一个元素。
菜鸟教程的例子是这样的:
function iter (a, i)
i = i + 1
local v = a[i]
if v then
return i, v
end
end
function ipairs (a)
return iter, a, 0
end
1
2
3
4
5
6
7
8
9
10
11
多状态的迭代器:将所有的状态信息封装到table内,将table作为迭代器的状态常量,因为这种情况下可以将所有的信息存放在table内,所以迭代函数通常不需要第二个参数。
菜鸟教程的例子是这样的:
array = {"Lua", "Tutorial"}
function elementIterator (collection)
local index = 0
local count = #collection
-- 闭包函数
return function ()
index = index + 1
if index <= count
then
-- 返回迭代器的当前元素
return collection[index]
end
end
end
for element in elementIterator(array)
do
print(element)
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
模块
模块的结构就是一个 table 的结构(表的相关函数),因此可以像操作调用 table 里的元素那样来操作调用模块里的常量或函数,如
-- 文件名为 module.lua
-- 定义一个名为 module 的模块
module = {}
-- 定义一个常量
module.constant = "这是一个常量"
-- 定义一个函数
function module.func1()
io.write("这是一个公有函数!\n")
end
local function func2()--外部不能直接访问
print("这是一个私有函数!")
end
function module.func3()--给予外部访问私有函数func2
func2()
end
return module
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
require 函数:require("<模块名>") 或者 require “<模块名>” 来加载模块。
在另外的脚本,加载模块的脚本,那么就可以调用我们写好的方法。如:
-- test_module.lua 文件
-- module 模块为上文提到到 module.lua
require("module")
print(module.constant)
module.func3()
1
2
3
4
5
——两个脚本要放在同一个文件夹内才能加载成功或者把模块脚本放到 LUA_PATH 环境变量的目录下也能加载成功。
协同程序
Lua 协同程序(coroutine)与线程比较类似,但是在任一指定时刻只有一个协同程序在运行,并且这个正在运行的协同程序只有在明确的被要求挂起的时候才会被挂起。
创建协程:coroutine.create(method)返回coroutine,用resume唤醒启动协程;coroutine.wrap(method)返回一个函数,直接调用函数启动协程。
coroutine.yield()在运行协程时,遇到这语句便会挂起协程。若有参数则会返回参数给resume,在下一次用resume唤醒的时候要同时传入参数。这样resume将外部状态(数据)传入到协同程序内部;而yield则将内部的状态(数据)返回到主程中。
coroutine.resume(“coroutineName”)唤醒协程。
文件 I/O
简单模式(simple model)拥有一个当前输入文件和一个当前输出文件,并且提供针对这些文件相关的操作。如:
-- 以只读方式打开文件(第二个参数是打开模式)
file = io.open("test.lua", "r")
-- 设置默认输入文件为 test.lua
io.input(file)
-- 输出文件第一行
print(io.read())
-- 关闭打开的文件
io.close(file)
1
2
3
4
5
6
7
8
完全模式(complete model) 使用外部的文件句柄来实现。(不用设置默认输入文件,直接操作)
-- 以只读方式打开文件
file = io.open("test.lua", "r")
-- 输出文件第一行
print(file:read())
-- 关闭打开的文件
file:close()
1
2
3
4
5
6
类的实现与继承
和C#那些思想一样,但是Lua是以表的形式实现,可供参考网址:
Lua类的实现:https://blog.csdn.net/cp790621656/article/details/49619655
Lua类的继承:https://blog.csdn.net/cp790621656/article/details/49625145
---------------------
作者:东菇
来源:CSDN
原文:https://blog.csdn.net/weixin_43701019/article/details/88200342
版权声明:本文为博主原创文章,转载请附上博文链接!