找回密码
 立即注册
首页 业界区 安全 服务器知识串讲(自用) - lua脚本语言篇 ...

服务器知识串讲(自用) - lua脚本语言篇

各卧唯 2025-6-1 00:12:28
基础语法


  • 单行和多行注释
  1. -- 这是一条注释
  2. --[[
  3. 多行注释
  4. 多行注释
  5. --]]
复制代码

  • 建议的命名规则按照:
    参数命名规则 n开头代表参数是number t开头代表是table b开头代表是bool
  • nil(空)
    nil 类型表示一种没有任何有效值,它只有一个值 -- nil,例如打印一个没有赋值的变量,便会输出一个 nil 值
    对于全局变量和 table,nil 还有一个"删除"作用,给全局变量或者 table 表里的变量赋一个 nil 值,等同于把它们删掉。lua gc机制会自动定时把这类数据进行回收
nil 作比较时应该加上双引号 ":
在c++中,全局非静态变量可不赋值,也可赋初值,静态全局变量默认赋值为0进行占位,c++中的 NULL 一般表示为0,nullptr 则指代一个空指针,也表示删除的意思

  • boolean(布尔)
    boolean 类型只有两个可选值:true(真) 和 false(假),Lua 把 false 和 nil 看作是 false,其他的都为 true,数字 0 也是 true:
  • b if a else c        a and b or c
模块是什么? 包是什么?

pkage.loaded[moudle_name]
所有加载过的模块都存在这种表里面
pkage.searcher 搜索器中去查找  preload 搜索器  lua搜索器
定义lua搜索器搜寻的路径
require “moudle”
先去已经加载过的模块表中查找
再去4大搜索器中找
lua中的pair 和ipair的区别?


  • 顺序遍历(从1开始)(ipair是顺序遍历)
  • 碰到nil就停止(ipair)(pair是哈希,碰到nil不停止)
lua的字符串操作?

Lua的字符串操作
点击查看代码
  1. print(string.format("格式化输出字符串%d",123))
  2. str = "abcDEfg"
  3. print("小写转大写"..string.upper(str))
  4. --大写转小写
  5. print("大写转小写"..string.lower(str))
  6. --反转字符串
  7. print("翻转字符串"..string.reverse(str))
  8. --字符串索引查找 索引从1开始
  9. --双返回值 查找字符串的首个字符和末尾字符的索引值
  10. print("字符串索引查找"..string.find(str,"DE"))
  11. --截取字符串 [a,b]双闭
  12. print("截取字符串"..string.sub(str,3,4))
  13. --字符串重复复制 第二个参数重复次数
  14. print("字符串重复复制"..string.rep(str,2))
  15. --字符串修改 参数(字符串,需要修改的字符串,用于替换的字符串)
  16. --返回两个参数,第一个是修改后的字符串 第二个参数是修改的次数
  17. print("字符串修改"..string.gsub(str,"DE","**"))
  18. --字符 转 ASCII码 第二个参数是字符串中指定位置的字符 索引从1开始
  19. a = string.byte("Lua",1) --L的ASCII码
  20. print("L的ASCII码"..a)
  21. --ASCII码转字符
  22. print("ASCII码转字符"..string.char(a))
复制代码
可变参数与返回值?

--变长参数的使用
--变长参数的使用需要先在函数内部用表存起来再对表进行相关操作
func4 = function(...)
arg = {...}
for i = 1,#arg do
print(arg)
end
end
--接收多返回值问题
tmp1,tmp2,tmp3 = func2(1,2,3) --当对应时会依次接收到三个返回值
--当接收参数少于返回值个数 会自动舍弃多余返回值
tmp1 = func2(1,2,3) --只有tmp1会接收到1
--当接收参数多于返回值个数 多余的默认为nil
tmp1,tmp2,tmp3,tmp4 = func2(1,2,3) --tmp4默认为nil
lua如何判空表?

if tbl and next(tbl)!=nil then print("table not nil") end
lua 是怎么实现深浅拷贝的?

点击查看代码
  1. a = 1
  2. b = a -- copy
  3. deepCopyTbl = function (tbl)
  4.   copy = function(tbl)
  5.     if not tbl and type(tbl) ~= "table" then --先看copy方法中的代码,如果这个类型不是表的话,就没有遍历的必要,可以直接作为返回值赋值;
  6.       return tbl;
  7.     end
  8.     local newTbl = {} --当前传入的变量是表,就新建一个表来存储老表中的数据,下面就是遍历老表,并分别将k,v赋值给新建的这个表,完成赋值后,将老表的元表赋值给新表。
  9.     for k,v in ipairs(newTbl) do --在对k,v进行赋值时,同样要调用copy方法来判断一下是不是表,如果是表就要创建一个新表来接收表中的数据,以此类推并接近无限递归。
  10.       newTbl[copy(k)] = copy(v)
  11.     end
  12.     return setmetatable(newTbl,getmetatable(tbl))
  13.   end
  14.   return copy(tbl)
  15. end
复制代码
lua中如何实现对表只读?

点击查看代码
  1. --- 强烈注意!!!! 如果你的table改动过元表 将其设为只读以后 在进行深拷贝元表无法继承 只能拷贝其中的值
  2. --- 调用这个函数以后 table内部所有层都会设为保护  如果你想对其重新设为保护则会报错 如果有特殊需求则需要深拷贝这个对象才可以重新设置保护
  3. --- 原生的next会失效 因为其无法调用到_index
  4. function M.readOnly(t)
  5.                 local locked = {}
  6.                 if not __G.proxiesCfg[t] then
  7.                         -- logInfo("新建一个只读的table 调用的位置:",M.print_stack(2))
  8.                         -- local newt = t
  9.                         locked = LOC.readOnlyBase(t)
  10.                         __G.proxiesCfg[t] = locked
  11.                 else
  12.                         locked = __G.proxiesCfg[t]
  13.                 end
  14.                 return locked
  15.     end
  16. end
  17. function LOC.readOnlyBase(t)
  18.         for k, v in pairs(t) do
  19.                 if type(v) == 'table' then
  20.                         local mt = getmetatable(v)
  21.                         if mt and mt["__index"] and __G.proxiesCfg[mt["__index"]] then
  22.                                 t[k] = __G.proxiesCfg[mt["__index"]]
  23.                         else
  24.                                 t[k] = LOC.readOnlyBase(v)
  25.                         end
  26.                 end
  27.         end
  28.         local locked = {}
  29.         local mt = {
  30.                 __index = t,
  31.                 __len = function()
  32.                         return #t
  33.                 end,
  34.                 __pairs = function(tt)
  35.                         return function(_, index)
  36.                                 return next(t, index)
  37.                         end, tt, nil
  38.                 end,
  39.                 __newindex = function(t, k, v)
  40.                         if t[k] then
  41.                                 logError("table数据只读 不允许修改旧值:",k,t[k],table_print(t[k]),table_print(v))
  42.                         else
  43.                                 logError("table数据只读 不允许添加新值:",k,t[k],table_print(t[k]),table_print(v))
  44.                         end
  45.                         local context = "table数据只是可读 不允许修改:"..debug.traceback()
  46.                         logError(context)
  47.                         __G.insertTracebackLog(context)
  48.                 end,
  49.                 __isReadOnly = true,
  50.         }
  51.         setmetatable(locked, mt)
  52.         return locked
  53. end
复制代码
lua 中的ipairs 和 pairs区别?

情况一:table组成由 哈希表(键值对,开链解决冲突),数组(数字,表)
那就根据元素类型进行分类,哈希表一组,数组一组,使用ipairs时候打印数组,使用哈希表时候打印全部,数组也当作kv值对进行操作。
情况二:数字和表混合
先哈希表再数值匹配
lua中的元表和元方法?

点击查看代码
  1. -- 对于string number bool基础数据类型
  2. A = {}
  3. B = {}
  4. setmetatable(
  5.     A,
  6.     {
  7.         __index = B, --索引查询
  8.         __newindex = B, --索引更新
  9.         __add = B, --加法
  10.         __sub = B, --减
  11.         __mul = B, --乘
  12.         __div = B, --除
  13.         __mod = B, --取模
  14.         __pow = B, --乘幂
  15.         __unm = B, --取反
  16.         __concat = B, --连接
  17.         __len = B, --长度
  18.         __eq = B, --相等
  19.         __lt = B, --小于
  20.         __le = B, --小于等于
  21.         __call = B, --执行方法调用
  22.         __tostring = B, --字符串输出
  23.         __metatable = B         --保护元表
  24.     }
  25. )
  26. --- 元表元方法的设置
  27. father = {  
  28.     prop1=2  
  29. }  
  30. father.__index = father -- 把father的__index方法指向它本身
  31. son = {  
  32.     prop2=1  
  33. }  
  34. setmetatable(son, father) --把son的metatable设置为father  
  35. print (son.prop1)
  36. --输出结果为2
复制代码
table的打印

点击查看代码
  1. local M = {}
  2. local tconcat = table.concat
  3. local tinsert = table.insert
  4. local srep = string.rep
  5. M.print_table = function(root)
  6.     local cache = {  [root] = "." }
  7.     local function _dump(t,space,name)
  8.         local temp = {}
  9.         for k, v in next, t do
  10.             local key = tostring(k)
  11.             if cache[v] then
  12.                 tinsert(temp,"+" .. key .. " {" .. cache[v].."}")
  13.             elseif type(v) == "table" then
  14.                 local new_key = name .. "." .. key
  15.                 cache[v] = new_key
  16.                 tinsert(temp,"+" .. key .. _dump(v,space .. (next(t,k) and "|" or " " ).. srep(" ",#key),new_key))
  17.             else
  18.                 tinsert(temp,"+" .. key .. " [" .. tostring(v).."]")
  19.             end
  20.         end
  21.         return tconcat(temp,"\n"..space)
  22.     end
  23.     print(_dump(root, "",""))
  24. end
  25. return M
复制代码
lua如何实现面向对象

点击查看代码
  1. --[[
  2. 模拟继承结构的基类
  3. ]]
  4. local _class = {}
  5. function Class(super)
  6.     local class_type = {}
  7.     class_type.ctor = false
  8.     class_type.super = super
  9.     class_type.New = function(...)
  10.         local obj = {}
  11.         do
  12.             local create
  13.             create = function(c, ...)
  14.                 if c.super then
  15.                     create(c.super, ...)
  16.                 end
  17.                 if c.ctor then
  18.                     c.ctor(obj, ...)
  19.                 end
  20.             end
  21.             create(class_type, ...)
  22.         end
  23.         setmetatable(obj, {__index = _class[class_type]})
  24.         return obj
  25.     end
  26.     local vtbl = {}
  27.     _class[class_type] = vtbl
  28.     setmetatable(
  29.         class_type,
  30.         {
  31.             __newindex = function(t, k, v)
  32.                 vtbl[k] = v
  33.             end,
  34.             --For call parent method
  35.             __index = vtbl
  36.         }
  37.     )
  38.     if super then
  39.         setmetatable(
  40.             vtbl,
  41.             {
  42.                 __index = function(t, k)
  43.                     local ret = _class[super][k]
  44.                     vtbl[k] = ret
  45.                     return ret
  46.                 end
  47.             }
  48.         )
  49.     end
  50.     return class_type
  51. end
复制代码
lua如何实现类?

在Lua中没有直接的类的相关语法,但是可以通过表来模拟继承
在Lua中表模拟类时,表中各元素之间相互独立因而表中方法无法像类一样直接调用其它元素,成员函数想要访问成员变量只能靠传参或传入表后利用表调用成员变量。
传入调用表更为通用,可自行定义一个参数用来接收调用表对象,用普通的点.调用时将表传入进去即可在函数内部利用表对象获取相应的成员变量了。
现实开发更常用冒号配合self完成上述功能。利用 冒号 : 可自动将调用者当作第一个参数传递给函数,在定义函数时采用 冒号:的定义方法 配合self的使用(self默认为函数参数的第一个参数),达到类调用成员变量的效果。
点击查看代码
  1. local ClassDefineMt = {}
  2. --继承基类的函数 如果使用基类存在子类不存在的函数时会去__tbl_Baseclass__寻找并设置
  3. function ClassDefineMt.__index( tbl, key )
  4.         local tBaseClass = tbl.__tbl_Baseclass__
  5.         for i = 1, #tBaseClass do
  6.                 local xValue = rawget(tBaseClass[i],key) --查询tBaseClass下面有没有对应的key或者函数
  7.                 if xValue then
  8.                         -- print("ClassDefineMt __index:",key)
  9.                         rawset( tbl, key, xValue ) --设置基类函数到子类table中
  10.                         return xValue
  11.                 end
  12.         end
  13. end
  14. ---允许多个基类
  15. function __G.class( ... )
  16.         local ClassDefine = {}
  17.         -- 这里是把所有的基类放到 ClassDefine.__tbl_Bseclass__ 里面
  18.         ClassDefine.__tbl_Baseclass__ =  {}
  19.         local arg = {...}
  20.         for index = 1, #arg do
  21.                 local tBaseClass = arg[index]
  22.                 --将基类存储进__tbl_Baseclass__
  23.                 table.insert(ClassDefine.__tbl_Baseclass__, tBaseClass)
  24.                 for i = 1, #tBaseClass.__tbl_Baseclass__ do
  25.                         --将基类的基类也写入__tbl_Baseclass__中 多重继承
  26.                         table.insert(ClassDefine.__tbl_Baseclass__, tBaseClass.__tbl_Baseclass__[i])
  27.                 end
  28.         end
  29.         -- 所有对实例对象的访问都会访问转到ClassDefine上 设置ClassDefine为元index
  30.         local InstanceMt =  { __index = ClassDefine } --先调用InstanceMt的__index然后在调用ClassDefine的__index找到对应的函数
  31.         --  IsClass 函数提供对象是否某种类型的检测, 支持多重继承
  32.         ClassDefine.IsClass = function(self, classtype)
  33.                 local bIsType = (self == classtype)
  34.                 if bIsType then
  35.                         return bIsType
  36.                 end
  37.                 for index=1, #self.__tbl_Baseclass__ do
  38.                         local baseclass = self.__tbl_Baseclass__[index]
  39.                         bIsType =  (baseclass == classtype)
  40.                         if bIsType then
  41.                                 return bIsType
  42.                         end
  43.                 end
  44.                 return bIsType
  45.         end
  46.         --构造函数参数的传递,只支持一层, 出于动态语言的特性以及性能的考虑
  47.         ClassDefine.new = function( self, ... )
  48.                 local oNewInstance = {}
  49.                 oNewInstance.__ClassDefine__ = self    -- IsType 函数的支持由此来
  50.                 oNewInstance.IsClass = function( self, classtype )
  51.                         return self.__ClassDefine__:IsClass(classtype)
  52.                 end
  53.                 -- 这里要放到调用构造函数之前,因为构造函数里面,可能调用基类的成员函数或者成员变量
  54.                 setmetatable( oNewInstance, InstanceMt )
  55.                 local funcCtor = rawget(self, 'Ctor')
  56.                 if funcCtor then
  57.                         funcCtor(oNewInstance, ... )
  58.                 end
  59.                 return oNewInstance
  60.         end
  61.         setmetatable( ClassDefine, ClassDefineMt ) --设置元索引函数
  62.         return ClassDefine
  63. end
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册