# lua-tutorial **Repository Path**: daizia/lua-tutorial ## Basic Information - **Project Name**: lua-tutorial - **Description**: lua 基础语法练习 - **Primary Language**: Lua - **License**: MPL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-04-08 - **Last Updated**: 2025-02-07 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ### 文档参考 [1. Lua 基础知识 - 《Lua编程入门》 - 书栈网 · BookStack](https://www.bookstack.cn/read/luaprimer/01.md) ### 代码参考 [bhlzlx/lua_api_tutorial: lua api tutorial by SNH48-久寿川 from 像素软件 (github.com)](https://github.com/bhlzlx/lua_api_tutorial) ### C API函数介绍 ```bash https://www.bookstack.cn/read/luaprimer/07.md 当Lua调用C函数时,被调用的C函数将得到一个新的堆栈。这一堆栈与之前调用此函数的堆栈无关,也有其它C函数的堆栈无关。这一新的堆栈用调用C函数要用到的参数初始化,同时,这一堆栈也被用以返回函数调用结果。 写应用程序主流程代码用lua_pcall,写C Native Function代码时用lua_call。 ``` ### 常用 ```lua --字符串拼接 '123' .. '\n' --如果数据量太大效率是很慢的-- 一般使用table.insert(t, line) --缺省值 a = a or 10 --三目运算符 A,B,C=1,2,3; B=false; D=(A and B) or C;--一个简单的三目 print(D); E=((A and {B}) or {C})[1];--这里才是一个合格的三目运算 print(E); --while:没有 continue 在lua 中,没有这些运算符 i++, i--, ++i, --i, +=, -= --a=b=1 这种写法会出错,不能连续赋值 --goto goto end print('abc') ::end:: print('cde') --ipairs遍历数组 --pairs遍历表 t1={11,22,"xxx",33,"nil",44,55,66,key="vvv",77}; for k,v in ipairs(t1) do print(k,v); end print('---------1---------') for k,v in pairs(t1) do print(k,v); end print('---------2---------') for i=1,5,1 do --初始值,结束值,步长 print(i,t1[i]) end --table常用函数 --table.concat(list, sep, i, j) 将数组中的元素拼接成一个字符串 --table.remove(list, pos) 删除数组中元素,默认删除最后一个 --table.insert(list, pos, value) 向指定位置插入元素,默认插入到最后 --table.sort(list, comp) 数组排序,默认从小到大,可自定义排序规则 --table.move(a1, f, e, t, a2) 把数组a1中的元素往a2中拷贝 --string常用函数 string.find()--字符串查找 string.gsub()--字符串替换 string.upper( )--转大写 string.lower( )--转小写 string.len( )--字符串长度 string.match()--正则匹配 string.sub()--字符串截取 --函数 --当返回值 function func4() return func1 end rs1=func4() rs1("abc",123) func4()("abc",123) --匿名函数当返回值 function func5() return function(a,b) print(a,b) end end rs2=func5() rs2("abc",123) func5()("abc",123) print("-----3--------") --多返回值 function func6() function func6_son1(a,b) print("son1",a,b) end function func6_son2(a,b) print("son2",a,b) end return func6_son1, func6_son2, func1, function (a,b) print("son-last",a,b) end end rs3,rs4,rs5,rs6=func6() rs3("abc",123) rs4("abc",123) rs5("abc",123) rs6("abc",123) ---用select 处理函数可变参 --select(n, ...) 表示获取可变参的一部份数据,从第n个位置开始 --select("#", ...) 表示获取可变参的元素个数 --求和 function func22(...) sum=0 count=select("#",...) for i=1,count do sum = sum + ((select(i,...))) end return sum,sum/count end print(func22(1,2,3,4,5)) ---table.pack(...) 将可变参打包成一个table,且会在最后多出一个n键,其对应的值是可变参的参数个数 ---table.unpack(list, i, j) 解包,将table 解成可变参 function func3() --return 1,2,3,4,5; return table.pack(11,22,33,4,5); end print(func3()); print(table.unpack(func3())); ---闭包---- local function func1(a,b) local x=0; local y=0; return function() x=x+1; -- 类似于static 属性 print(a,b,x,y) end end --创建一个闭包 tmpFunc = func1("abc",123); tmpFunc(); tmpFunc(); tmpFunc(); tmpFunc3=tmpFunc; tmpFunc3(); print("-------4--------"); --新建一个闭包 tmpFunc2 = func1("abc",123); tmpFunc2(); --利用闭包实现迭代器 t1={11,22,33,nil,nil,44,55} function myIpairs(tab) local index=0 local count=#tab return function() index = index+1 if index <= count then ::FLAG:: if tab[index] == nil then index = index+1 goto FLAG end return index,tab[index] end end end for k,v in myIpairs(t1) do print(k,v); end ``` ### 元表和元方法 ```lua --运算符重载 __add/__sub/__eq t1 = {11,22,33} t2 = {1,2,3} metaT3={ __add = function () local rs={}; local len1=#t1; local len2=#t2; if len1 > len2 then len2=len1; end for i=1,len2 do local a=t1[i] or 0; local b=t2[i] or 0; rs[i]=a+b; end return rs; end } setmetatable(t1, metaT3) setmetatable(t2, metaT3) t4 = t1+t2 for key, value in pairs(t4) do print(key,value) end --[[ __index 索引取值,表去他的元表的__index指向的表或者函数取 __newindex给表赋值 元表 metatable __index 当在一个表中,去取某个key,如果该表中有对应的key,就直接返回 如果没有,看有没有元表,没有元表,返回nil 有元表,看元表中有没有__index 没有,返回nil 有: 如果__index 是个表,并且有key, 返回值;没有key, 返回nil 如果 __index 是个function;则直接调用该function ,且表和key 都会作为该function 的参数 __newindex 如果元表的__newindex是一个表,则给本表里面设一个没有的key的时候, 会写到元表的__newindex 对应的表中,而不会写本表,如果本表中有key,则更新本表,不会管元表。 如果元表的__newindex是一个表是function,则直接调用,且本表,key,value 都可作参数 ]] t1={id=123,name="tom"} metaT3={ --可以直接赋值,这样可以赋值的时候添加额外操作 __newindex=function(t,k,v) --print(tostring(t).." 被写入 "..k.." : "..v); --t[k]=v; --stack overflow 死递归,爆栈了 rawset(t,k,v);--调用原生方法,不调用重载的方法,写到原表中 end }; setmetatable(t1,metaT3) t1["phone"]="18551165662" --当有__newindex 的时候,就写到对应的__newindex 的表中去了 print(t1.phone) --[[ __tostring 用函数接管本表的返回值 返回一个string __call 把表当类处理,此处类似于类中的构造函数,可传值,本表是第一个参数 rawget(table, index) 取本表中的index 索引对应的值,不受元表干扰,没有就返回nil; rawset(table, index, value) 给本表添加元素,不受元表干扰 ]] --self:语法糖 --自索引,为了调用元表中__index指向的表的方法和成员属性,当元表中的__index指向元表自己,就是所谓的自索引 t1={id=123,name="tom"}; t2 = { hello = function () print('hello') end, } --t2.__index=t2 --必须加上此行不然报错 setmetatable(t1,t2) t1.hello() -------------------类的实例化------------------------- userInfo={id=123,name="tom",age=99}; userInfo.__index=userInfo; function userInfo:new(obj) obj=obj or {}; setmetatable(obj,self); return obj; end function userInfo:setAge(val) self.age=self.age+val; --取 userInfo 的age + val,再写给u3 end u1=userInfo; u2=u1; u3=userInfo:new({id=456}); print(u2.age,u3.age); u3:setAge(100); print(u2.age,u3.age);--99 199 --------------------------------------------- ``` ### 包管理 ```bash require ('module') -- 会依次搜索: -- 当前脚本目录下的module.lua -- LUA_PATH路径下的module.lua # export LUA_PATH="~/lua/?.lua;;"文件路径以 ";" 号分隔,最后的 2 个 ";;" 表示新加的路径后面加上原来的默认路径 -- package.path路径下的module.lua #当 Lua 启动后,会以环境变量LUA_PATH的值来初始这个package.path环境变量 -- 如果找过目标文件,则会调用 package.loadfile 来加载模块。否则,就会去找 C 程序库。 -- 搜索的文件路径是从全局变量 package.cpath 获取,而这个变量则是通过环境变量 LUA_CPATH 来初始。 -- 搜索的策略跟上面的一样,只不过现在换成搜索的是 so类型的文件。如果找得到,那么 require 就会通过 package.loadlib 来加载它。 #package.preload是一张表,其中的键(key)是模块名,而值(value)是一个函数,用于加载和初始化对应的模块 #package.path和package.cpath都是字符串指定路径 ``` ### 命令行参数 ```bash #2、脚本名索引为0 lua -e "sin=math.sin" script.lua a b arg[-3] = "lua" arg[-2] = "-e" arg[-1] = "sin=math.sin" arg[0] = "script" arg[1] = "a" arg[2] = "b" loadlib --加载动态库 assert error() ```