拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Lua 语言速查清单:从基础语法到标准库的完整实战参考(Quick Reference 速查表解析)

Lua 语言速查清单从基础语法到标准库的完整实战参考Quick Reference 速查表解析【免费下载链接】reference面向开发者的技术速查清单Cheat Sheets集合整理常见技术、工具与开发流程帮助快速查阅关键信息提高开发效率。项目地址: https://gitcode.com/GitHub_Trending/referen/reference本篇技术指南以开源仓库 Quick Reference 中的 Lua 备忘清单 为骨架展开系统梳理 Lua 语言的安装运行、数据类型、控制流、函数、字符串与数学标准库、table 数据结构以及模块机制等核心内容。无论你是要快速查阅某个 API 用法还是想以速查方式入门 Lua 脚本编写读完后都能直接复制文中示例上手实践。本仓库README.md是一个面向中文开发者的技术速查清单集合Lua 速查表正是其中“编程”分类下的一份完整文档源码以 Markdown 形式维护于 docs/lua.md并配有针对该条目的品牌图标 assets/lua.svg。下面按原文档脉络逐节展开并在关键处结合 Lua 语言特性补充原理性说明。快速上手安装与第一个 Lua 程序安装 LuamacOS 下推荐使用 Homebrew 安装$ brew install lua其它获取方式如 Windows、Linux 发行版可以从 Lua 官方下载页面获取预编译二进制或通过各发行版的软件包管理器安装。安装完成后用下面的命令确认 Lua 是否可用# 查看 lua 是否安装成功 $ lua -v如果输出版本号例如Lua 5.4.x说明解释器已就绪。Hello World 与两种运行方式新建hello.lua文件内容如下#!/usr/bin/env lua print(Hello World!)第一行是 shebang仅在把脚本当作可执行文件直接运行时需要。运行方式有两种$ lua ./hello.lua # 或者也可以像 bash 脚本一样 $ chmod x hello.lua ./hello.lua第一种是显式调用解释器执行第二种先给脚本添加可执行权限再像 shell 脚本一样直接运行此时依赖 shebang 行找到lua解释器。注释单行注释以两个减号开始-- 以两个减号开始多行注释以--[[开头以]]结尾--[[ 这里是多行注释 可以跨越多行 ]]数据类型与基础语法type() 函数判断值类型Lua 是动态类型语言使用type()函数可以判断变量或者值的类型print(type(true)) -- boolean print(type(nil)) -- nilLua 共有八种基本类型nil、boolean、number、string、function、userdata、thread和table它们都会由type()返回对应的字符串名称。number唯一的数值类型Lua 默认只有一种 number 类型 double双精度类型整数与小数共用这一类型从 Lua 5.3 开始number 内部进一步区分了 integer 与 float 两个子类型详见后文math.type但对外暴露的仍是统一的 number 类型print(10) -- 整数 print(0.3) -- 小数 print(2e10) -- 科学计数法即 2×10^10注意科学计数法写法中间不能有空格2e10是一个合法数字字面量。string字符串的三种写法字符串可以用单引号或双引号表示-- 使用 local str1 str1 -- 使用 local str2 str2当字符串需要跨越多行例如内嵌 HTML、长文本时使用长括号[[]]local html [[ html head/head body a hrefhttps://www.twle.cn/ 简单编程 /a /body /html ]] print(html)长括号内的换行与空格会被原样保留且其中无需转义引号。字符串连接..Lua 使用两个点..作为字符串连接运算符print(a .. b) -- ab print(157 .. 428) -- 157428注意第二个例子number 与 number 用..连接时两侧会被自动转换为字符串最终结果是字符串157428。字符串长度#一元运算符#可以取得字符串的字节长度print(#string) -- 6tableLua 唯一的数据结构table 是 Lua 中唯一的复合数据结构既可以当作数组也可以当作字典关联数组使用local table {}迭代 table默认的初始索引会从 1 开始local array { apple, pear, orange, grape } print(array[1]) -- apple for k, v in pairs(array) do print(k .. : .. v) end -- 1 : apple -- 2 : pear -- 3 : orange -- 4 : grapepairs会遍历表中所有键值对与之相对ipairs只从索引 1 开始连续遍历到第一个 nil 为止适合纯数组场景。指定键table 既可以用点号访问字段也可以用方括号加字符串键访问local array {} array.one apple array[two] peach print(array.one) -- apple print(array.two) -- peacharray.one等价于array[one]两种写法可以混用。变量默认值与作用域默认值变量在赋值前的默认值都是nil#!/usr/bin/env lua print(b) -- nil全局与局部变量Lua 中的变量默认全是全局变量哪怕是语句块或是函数里除非用local显式声明为局部变量#!/usr/bin/env lua function main() local b 12 a 23 end main() print(a) -- 23 print(b) -- nila未加local因此在函数内赋值后成为全局变量函数外仍可访问b是局部变量离开函数作用域后不可见。赋值多重赋值与交换赋值可以同时改变变量和 table 字段a hello .. world -- 改变 变量 t.n t.n 1 -- 改变 tableLua 支持一次给多个变量赋值且赋值语句右侧的所有表达式会先求值完毕再统一赋给左侧-- 给多个变量赋值 -- 情况1a 未定义过 a, b 10, 2*a -- 报错a 是 nil -- 情况2a 已定义比如 a5 a 5 a, b 10, 2*a -- 右侧的 a5结果 a10, b10不会报错情况 1 中a从未被赋值求值2*a时a还是 nil对 nil 做算术运算会直接报错情况 2 中右侧先按旧值a5求出b10随后a才被更新为 10。正是“先右后左”的求值顺序让交换变量变得非常简单local x, y 1, 3 x, y y, x print(x, y) -- 3, 1table 字段同样可以参与多重赋值交换local tab {} tab.one 2 tab.two 1 tab[one], tab[two] tab.two, tab.one print(tab.one, tab.two) -- 1 2赋值个数不一致如果变量个数大于值的个数按变量个数补足 nila, b, c 1, 3 print(a,b,c) -- 1 3 nil如果变量个数小于值的个数多余的值会被忽略a 1 local a, b a, a 1, a 2 print(a, b) -- 1 2右侧三个值中a2被丢弃且新的局部a遮蔽了旧值。算术运算符Lua 的算术运算符及其含义如下| 符号 | 含义 | | :- | :- | || 加法 | |-| 减法 | |*| 乘法 | |/| 除法 | |%| 取余求出除法的余数 | |^| 乘幂计算次方 | |-| 负号取负值 |实际运行示例local a, b 4, 3 print(a b) -- 7 print(a - b) -- 1 print(a / b) -- 1.3333333333333 print(a * b) -- 12 print(a % b) -- 1 print(a ^ b) -- 64.0注意除法/的结果始终是浮点数乘幂^的结果也以浮点数形式呈现。类型转换Lua 在特定上下文中会自动进行类型转换在算术运算中string 类型会尝试自动转换为 numberlocal a, b, c str, 1, 2 -- print(a b) -- error print(b c) -- 3str无法转换为数字所以a b会报错而1 2自动转换为1 2结果是3。number 类型使用..会自动转换为 stringlocal a, b 1, 2 print(type(a .. b))连接结果12是字符串type()返回string。也可以显式转换使用tostring与tonumberprint(type(tostring(12))) -- string print(type(tonumber(12))) -- numbergoto 语句Lua 5.2 起支持goto用于无条件跳转到函数内的标签标签写法为::标签名::local function isValidNumber(num) if type(num) ~ number then goto invalidNumber -- 无条件地跳转到代码中的标签 ::invalidNumber:: end print(Valid number:, num) return true ::invalidNumber:: print(Invalid number:, num) return false end isValidNumber(123) -- 输出: Valid number: 123 isValidNumber(abc) -- 输出: Invalid number: abcgoto的典型用途是提前跳出嵌套循环或在函数内实现统一错误出口使用时需保证标签定义在同一个函数体内。条件与循环控制关系运算符| 符号 | 含义 | | :- | :- | || 等于 | |~| 不等于 | || 大于 | || 小于 | || 大于等于 | || 小于等于 |注意 Lua 的不等于是~而不是其他语言常见的!local a, b 4, 3 print(a b) -- false print(a b) -- false print(a b) -- false print(a ~ b) -- true print(a b) -- true print(a b)-- true逻辑运算符| 符号 | 含义 | | :- | :- | |and| 逻辑与 | |or| 逻辑或操作符 | |not| 逻辑非操作符 |local a, b true, false print(a and b) -- false print(a and not b) -- true print(a or b) -- trueLua 中and/or遵循“短路求值”且返回的不一定是布尔值而是参与运算的操作数and在第一个操作数为假时返回它否则返回第二个操作数or在第一个操作数为真时返回它否则返回第二个操作数。这一特性常被用来写默认值例如local name input or default。真相值0 为真nil 为假Lua 的判断规则与其他语言差异明显只有false和nil是假值其它一切值包括 0、空字符串、空 table都是真值。if(0) then print(0 为 true) end上面这段代码会正常输出0 为 true。而nil可以用在条件中当作false。if / elseif / elselocal age 27; if (age 18) then print(age 小于 18) elseif (age 25) then print(age 小于 25) elseif (age 30) then print(age 小于 30) else print(age 大于 30) end print(age 的值为 :, age)then与end是不可省略的关键字elseif是连写的中间没有空格。上面的例子中age27会命中第三个分支输出age 小于 30。while 循环local num 1 while (num 5) do print(num 的值为:, num) num num 1 end条件在每次循环体执行前判断当num增长到 5 时循环结束。for 循环三参数数值循环Lua 的数值 for 循环语法为for i 初始值, 限制值, 步长 do ... endfor i 10, 1, -1 do print(i) end使用要点lua 中的 for 循环从参数 1 变化到参数 2每次变化以参数 3 为步长递增 i并执行一次表达式参数三步长是可选的如果不指定默认是 1参数二限制值只会在一开始求值其后不会再进行运算。最后一点通过下面的例子可以验证——限制值表达式f(5)只会被调用一次local f function(x) print(in f(x) ) return x * 2 end for i 1, f(5) do print(i) end输出中in f(x)只出现一次随后依次打印1到10。repeat...until 循环repeat...until与 while 相反循环条件在当前循环结束后判断因此循环体至少会执行一次local num 11 repeat print(num 的值为: , num) num num 1 until (num 10) -- num 的值为11即使初始条件已经满足11 10循环体仍然执行了一次。break 跳出循环break用于无条件终止当前循环local num 11 repeat print(num 的值为: , num) num num 1 if (num 15) then break end until (num 20)当num增长到大于 15 时触发break即使until的条件num 20尚未满足循环也会立即结束。函数函数的定义与初始化像变量一样函数默认也是全局的如果加上local那么就是局部函数local function main() print(这是一个局部函数) end你也可以将函数赋值给一个变量匿名函数写法local main function() print(这是一个局部函数) end两种写法等价都定义了一个局部函数main。返回值函数使用return返回结果local function min(a, b) if (a b) then return a else return b end end print(min(1, 2))参数函数也可以作为参数传递函数是“一等公民”可以像普通值一样传入其它函数回调local p function(res) print(打印自己的风格, res) end local function main(a, b, p) p(a b) end main(1, 2, p)main接收两个数字和一个函数计算ab后交给回调函数p打印。多个返回值Lua 函数可以同时返回多个值local function min(a) local sum 0 local factorial 1 for i, v in pairs(a) do sum sum v factorial factorial * v end return sum, factorial end local a, b min({ 1, 2, 3, 4 }) print(a, b)传入{1, 2, 3, 4}sum累加得到 10factorial连乘得到 24一次调用返回两个结果再通过多重赋值分别接收。可变参数...函数可以接收不定数量的参数在函数体内部用...收集再用{...}包装成 table 处理local function average(...) local result 0 local arg { ... } for i, v in ipairs(arg) do result result v end return result / #arg end print(平均值为, average(1, 3, 5, 7, 9, 11))ipairs按顺序遍历所有实参并累加最后除以参数个数#arg得到平均值6。字符串标准库常用字符串方法| 方法 | 作用 | | :- | :- | |string.upper(s)| 全部转换为大写 | |string.lower(s)| 全部转换为小写 | |string.gsub(s, pattern, repl [, n])| 按模式替换可指定替换次数默认全部替换 | |string.find(s, pattern [, init])| 查找第一个匹配位置返回起止下标未找到返回 nil | |string.reverse(s)| 字符串反转 | |string.format(fmt, ...)| 格式化字符串说明符与 C 的 printf 类似 | |string.char(...)| 将整数按 ASCII/UTF-8 转为字符并拼接 | |string.byte(s [, i])| 返回指定位置字符的整数值默认第一个字符 | |string.len(s)| 计算字符串长度 | |string.rep(s, n)| 返回字符串的 n 个拷贝 | |string.sub(s, i [, j])| 剪切字符串第三个参数可选默认到字符串末尾 |逐一验证-- 全部转换为大写 string.upper(str) -- STR -- 全部转换为小写 string.lower(STR) -- str -- 指定替换的字符串个数, 最后一个参数可选默认是全部替换 string.gsub(aaaa, a, b, 3) -- bbba 3 string.gsub(Today is 29/01/2019, %d%d/%d%d/%d%d%d%d, a good day.) -- Today is a good day. -- 查找第一个匹配的字符串第三个参数可以提供开始查找的位置默认从 1 开始 -- 如果未找到则返回 nil string.find(referference, fer) -- 3 5 string.find(Today is 29/01/2021, %d%d/%d%d/%d%d%d%d) -- 10 19 -- 字符串反转 string.reverse(fw) -- wf -- 格式化字符串 string.format(value:%c, 1) -- value:a -- 转换字符并拼接 string.char(97,98,99,100) -- abcd -- 将字符转化为整数值。 int 用来指定某个字符默认第一个字符 string.byte(ABCD,4) -- 68 -- 计算字符串长度 string.len(abc) -- 3 -- 返回字符串的 n 个拷贝 string.rep(fw, 2) -- fwfw -- 剪切字符串第三个参数可选默认是字符串长度 string.sub(referference, 5, 6) -- rf几点说明string.gsub会返回两个值替换后的字符串和替换次数因此第一个例子输出bbba 3string.find的返回值是匹配子串的起始与结束下标例如referference中fer位于第 3 到第 5 个字符%d这类写法是 Lua 模式匹配中的字符类见下节所以gsub和find都可以直接匹配数字模式。正则匹配模式字符类Lua 的模式匹配pattern matching提供了一套以%开头的字符类常用对照如下| 模式 | 含义 | | :- | :- | |%a| 与任何字母配对 | |%c| 与任何控制符配对例如\n | |%d| 与任何数字配对 | |%l| 与任何小写字母配对 | |%p| 与任何标点punctuation配对 | |%s| 与空白字符配对 | |%u| 与任何大写字母配对 | |%w| 与任何字母/数字配对 | |%x| 与任何十六进制数配对 | |%z| 与任何代表 0 的字符配对 |大写的字符类如%D、%S表示对应小写字符类的补集。模式中()用于捕获、*、-、?用于表示重复次数。string.matchstring.match(s, pattern [, init])返回第一个匹配结果第三个参数可选默认从 1 开始。如果没有捕获组返回整个字符串匹配失败返回 nilstring.match( I have 2 questions for you., (%d) (%a) ) -- 2 questions(%d)捕获连续数字2(%a)捕获连续的单词questions两个捕获组依次作为返回值返回。string.gmatchstring.gmatch(s, pattern)返回一个迭代器函数每次调用迭代器函数返回下一个匹配如果参数 pattern 描述的字符串没有找到迭代函数返回 nil。常配合 for 循环使用for world in string.gmatch(I have 2 questions for you., %a) do print(world) end -- I -- have -- questions -- for -- you%a匹配连续的字母序列因此逐个抽取出句子中的所有英文单词数字2因不是字母而被跳过。数学标准库常用方法-- 一个比任何数字都大的浮点数 math.huge -- 最小值的整数 math.mininteger local a math.abs(-1) -- 1 -- 返回不小于该数到最小整数 local b math.ceil(1.2) -- 2 -- 返回不大于该数到最大整数 local c math.floor(1.2) -- 1 -- 取余 local d math.fmod(9.9, 9) -- 0.9 -- 返回最大值 local g math.max(1, 2, 3) -- 3 -- 返回最小值 local h math.min(1, 2, 3) -- 1 -- 返回参数的平方根 local r math.sqrt(9) -- 3说明math.huge表示正无穷大math.mininteger表示最小的整数值ceil向上取整、floor向下取整math.fmod是浮点数取余。工具方法-- 返回数字的类型 local l math.type(1.2) -- float local m math.type(3) -- integer local n math.type() -- nil -- 返回以指定底底对数 local e math.log(4, 2) -- 2 -- 返回以 e 为底的自然对数 local f math.exp(2) -- 7.3890560989307 -- 返回 [0,1) 区间内一致分布的浮点伪随机数 math.random() -- 返回 [1, n] 区间内一致分布的整数伪随机数 math.random(10) -- 返回 [n, m] 区间内一致分布的整数伪随机数 math.random(10, 100) -- 无符号整数比较参数一 小于 参数二 则返回 true否则返回 false local o math.ult(1, 10) -- 如果参数可以转换为一个整数则返回该整数否则返回 nil local p math.tointeger(3) -- 3 local q math.tointeger(0.32) -- nil -- 返回整数和小数部分 local i, j math.modf(3.14) -- 3 0.14其中math.type的存在印证了前面提到的Lua 5.3 起 number 在内部区分float与integer两种子类型math.random的三种调用形式分别覆盖无参、单参和双参区间场景math.ult提供无符号整数比较。三角与角度转换-- 圆周率 math.pi -- 3.1415926535898 -- 正弦方法以下皆是以弧度表示 math.sin(math.pi / 2) -- 1.0 -- 余弦方法 math.cos(math.pi) -- -1.0 -- 正切方法 math.tan(math.pi / 4) -- 1.0 -- 反正弦方法以下皆是以弧度表示 math.asin(1.0) -- 1.5707963267949 -- 反余弦方法 math.acos(1.0) -- 0.0 -- 反正切方法 math.atan(1.0) -- 0.78539816339745 -- 角度转换为弧度 math.rad(90) -- 1.5707963267949 -- 弧度转换为角度 math.deg(math.pi) -- 180.0注意所有三角函数的参数与返回值均以弧度为单位math.rad与math.deg负责角度与弧度之间的换算。table 标准库初始化数组初始化一个空数组local array {}默认的数组索引从 1 开始可以按顺序追加元素local array { a, b, c, d } array[5] e for i 1, 5 do print(array[i]) end这里array[5] e直接在第 5 个位置写入新元素补齐了数组的连续索引。多维数组table 可以嵌套形成多维数组local array { { a, b, c }, { d, e, f } } for i 1, #array do for j 1, #array[i] do print(array[i][j]) end end外层#array得到行数 2内层#array[i]得到每行列数 3双层循环遍历全部元素。初始化 table 与删除table 可以混合使用点号与方括号初始化字段local table {} table.name fw table.age 18 table[sex] boy -- 获取 table 的长度 print(#table) -- 0 -- 如果想要删除一个 table那么可以使用 nil 赋值 table nil print(table)注意#只对连续整数键的“序列”部分有效这里name/age/sex都是字符串键不属于数组部分所以#table返回 0。删除一个 table 或字段的通用做法就是把它赋值为nil。table 方法-- 用于连接 table 中指定的元素 -- table.concat(table [, sep [, start [, end]]]) local a { apple, orange, peach } print(table.concat(a, -, 2, 3)) -- orange-peach -- 用于向指定闻之插入元素。默认数组末尾 -- table.insert(table, [pos,] value) local a { apple, orange, peach } table.insert(a, 1, pear) print(a[1]) -- pear -- table.move(a1,f,e,t[,a2]) -- 表a1a1下标开始位置fa1下标结束位置et选择移动到的开始位置(如果没有a2默认a1的下标) local array { a, b, c } for i,v in pairs(table.move(array, 1, 3, 2)) do print(v) end -- a a b c -- table.sort (table [, comp]) -- 排序默认是升序 local array { a, c, b } local f function(a, b) return string.byte(a) - string.byte(b) 0 end table.sort(array, f) for i, v in pairs(array) do print(v) end -- c b a方法签名速记table.concat(t [, sep [, i [, j]]])用分隔符sep连接下标i到j的元素返回拼接后的字符串table.insert(t, [pos,] value)默认在数组末尾插入指定pos时插入到该位置并后移后续元素table.move(a1, f, e, t [, a2])把a1中下标f到e的元素移动到目标起始位置t未指定a2时默认仍在a1内上述例子把{a,b,c}平移到下标 2 起始处得到a a b ctable.sort(t [, comp])默认升序comp(a, b)返回 true 表示 a 应排在 b 之前。例子中的比较函数让较大的字符排在前面因此结果是降序c b a。迭代器无状态的迭代器无状态迭代器由三个要素组成迭代函数、状态常量、控制变量直接放入 for 循环中驱动function square(d,n) if n d then n n 1 return n, n*n end end for i,n in square,5,0 do print(i,n) end这里的square是迭代函数5是状态常量上限0是控制变量的初始值起始下标。每次迭代n自增 1 并返回(n, n*n)当n达到上限后迭代函数不再返回值循环终止依次打印(1,1)到(5,25)。for 循环迭代器更常见的做法是使用pairs驱动泛型 for 循环for i, n in pairs({ 1, 2, 3, 4 }) do print(i, n) end模块系统定义模块Lua 没有原生的class或package语法模块的惯用做法是创建一个 table把公开函数和字段挂上去最后return该 table。新建a.lua-- a.lua local mod {} mod.cool this is a mod function mod.test() print(this is a function) end return mod导入模块一般我们可以直接使用require导入-- b.lua -- local mod require(a) -- 使用 pcall 确保 require 函数导入成功失败则返回一个 false 状态 local status, mod pcall(require, a) if not status then return end mod.test() print(mod.cool)require会按package.path中的路径查找模块文件并缓存加载结果。用pcallprotected call保护性调用包一层的好处是即使模块不存在或加载报错程序也不会直接崩溃而是返回false与错误信息status为 false 时提前return避免后续访问空 table 出错。私有函数模块内部的辅助函数可以用local声明这样它们只对模块文件内部可见对外仅暴露通过 table 挂载的公开函数local mod {} local function private() print(private) end function mod.public() private() end return mod外部只能调用mod.public()无法直接访问private——这与本文前面“局部变量离开作用域即不可见”的规则一脉相承是 Lua 实现信息隐藏的标准手法。总结与延伸阅读本文完整继承了 docs/lua.md 的全部内容并做了源码级展开从安装运行、类型系统、控制流、函数到字符串/数学/table 三大标准库再到模块与私有函数封装基本覆盖了日常编写 Lua 脚本所需的高频知识点。几个值得记住的语言特性可以当作速查锚点变量默认全局local显式声明局部未赋值变量的值为nil只有false与nil是假值0为真数组索引从 1 开始#取序列长度..连接字符串~表示不等于pairs遍历全部键值对ipairs只遍历连续整数键多重赋值遵循“右侧先全部求值再统一赋值”因此可直接交换变量。若想继续深入本仓库还提供了文档排版与写作规范docs/quickreference.md以及大量与 Lua 配套使用的技术速查清单均可从 README.md 的目录入口进入查阅。Lua 语言本身的完整规范与参考手册可进一步阅读 Lua 官方文档lua.org与官方手册中关于string、math、table库的章节。【免费下载链接】reference面向开发者的技术速查清单Cheat Sheets集合整理常见技术、工具与开发流程帮助快速查阅关键信息提高开发效率。项目地址: https://gitcode.com/GitHub_Trending/referen/reference创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门