当前位置: 首页 > news >正文

Lua脚本详解

一、两种交互模式

1.1 命令行模式

直接在命令行中输入语句,回车即可看到运行结果;

在任意目录下使用lua命令进入lua命令行模式,在其中输入语句后回车即可运行显示出结果,使用ctrl+C退出模式;lua对语句后的分号要求不是强制性的,有没有都行;

1.2 脚本文件模式

先要编写脚本文件,然后再使用 lua 命令来运行文件;

例如,在当前用户主目录中新建一个 script 目录,在其中创建一个名称为 hello.lua 的文件,文件中就写一名 print()语句即可;

print("hello lua");

二、脚本运行方式

2.1 lua命令方式

2.2 可执行文件方式

1. 修改脚本文件内容,表示当前文件将使用 /usr/bin/lua 命令来运行;

#!/usr/bin/lua
print("hello lua");

2. 修改脚本文件权限

# 为脚本文件赋予可执行权限
chmod 755 hello.lua

3. 运行

三、Lua语法基础

3.1 注释

Lua 的行注释为两个连续的减号,段注释以  --[[  开头,以 ]]--  结尾;

在开头的  --[[  前再加一个减号,即可使段注释不起作用。其实就是使两个段注释标识变为了两个行注释。

3.2 数据类型

Lua 中有 8 种类型,分别为:nilbooleannumberstringuserdatafunctionthread  table。通过 type()函数可以查看一个数据的类型,例如,type(nil)的结果为 niltype(123)的结果为 number

3.3 标识符

程序设计语言中的标识符主要包含保留字、变量、常量、方法名、函数名、类名等。

Lua 的标识符由字母、数字与下划线组成,但不能以数字开头Lua 是大小写敏感的

3.3.1 保留字

3.3.2 变量

Lua 是弱类型语言,变量无需类型声明即可直接使用。变量分为全局变量与局部变量。

Lua 中的变量默认都是全局变量,即使声明在语句块或函数里。全局变量一旦声明,在当前文件中的任何地方都可访问。局部变量 local 相当于 Java 中的 private 变量,只能在声明的语句块中使用。 

3.3.3 动态类型

Lua 是动态类型语言,变量的类型可以随时改变,无需声明。

3.4 运算符

3.5 函数

Lua 中函数的定义是以 function 开头,后跟 函数名 参数列表,以 end 结尾。其可以没有返回值,也可以一次返回多个值。

3.5.1 固定参函数

其不要求实参的个数必须与函数中形参的个数相同。如果实参个数少于形参个数,则系统自动使用 nil 填充;如果实参个数多于形参个数,多出的将被系统自动忽略。

# 定义一个普通函数,包含两个形参
function f(a, b)print(a, b)
endf()        # nil   nilf(10)      # 10    nilf(10, 20)  # 10    20f(10, 20, 30)  # 10    20
# 定义一个普通函数,包含两个形参
function f(a, b)print(a, b, c)
endf()        # nil   nil   nilf(10)      # 10    nil   nilf(10, 20)  # 10    20    nilf(10, 20, 30)  # 10    20    nil

3.5.2 可变参函数

在函数定义时不给出具体形参的个数,而是使用三个连续的点号。

在函数调用时就可以向该函数传递任意个数的参数,函数可以全部接收。

# 定义一个普通函数,包含可变参数
function f(...)local a,b,c,d=...print(a, b, c, d)print(...)
endf(10, 20, 30)        # 10 20 30 nil
# 10 20 30f(10, 20, 30, 40)      # 10 20 30 40
# 10 20 30 40f(10, 20, 30, 40, 50)  # 10 20 30 40
# 10 20 30 40 50

3.5.3 可返回多个值

Lua 中的函数一次可以返回多个值,但需要有多个变量来同时接收。

function f(a, b)local sum = a + blocal mul = a * breturn sum mul;
end# 一次性接收两个值
m, n = f(3, 5)
print(m, n)    # 8  15

3.5.4 函数作为参数

Lua 的函数中,允许函数作为参数。而作为参数的函数,可以是已经定义好的普通函数,也可以是匿名函数。

function sum(a, b)return a + b
endfunction mul(a, b)return a * b
endfunction f(m, n, fun)local result = fun(m, n)print(result)
endf(3, 5, sum)    # 8
f(3, 5, mul)    # 15# 匿名函数调用
f(3, 5, function(a, b)return a - b;end        
);                # -2

3.6 流程控制语句

a = 5
if a>0 thenprint("num > 0")
elseif num == 0 thenprint("num = 0")
elseprint("num < 0")
enda = 3
while a>0 doprint(a)a = a - 1
endrepeatprint(a)a = a - 1
until a <= 0# i是执行的循环变量
# 10 为循环起始值
# 50 为循环结束值
# 20 为循环步长
for i=10, 50, 20 doprint(i)
end
# 10 30 50
for i=1, 9 doprint(i)if i == 5 thenbreakend
end
# 1 2 3 4 5

3.6.1 goto语句

funtion f(a)::flag::print("==========")if a>1 thenprint(a)a = a - 1goto flagend
endf(5)

goto 语句可以将执行流程无条件地跳转到指定的标记语句处开始执行,注意,是开始执行,并非仅执行这一句,而是从这句开始后面的语句都会重新执行。当然,该标识语句在第一次经过时也是会执行的,并非是必须由 goto 跳转时才执行。

四、语法进阶

4.1 table

4.1.1 数组

使用 table 可以定义一维、二维、多维数组。不过,需要注意,Lua 中的数组索引是从 1 开始的,且无需声明数组长度,可以随时增加元素。当然,同一数组中的元素可以是任意类型。 

4.1.2 map

使用 table 也可以定义出类似 map key-value 数据结构。其可以定义 table 时直接指定 key-value,也可单独指定 key-value。而访问时,一般都是通过 table key 直接访问,也可以数组索引方式来访问,此时的 key 即为索引。

4.1.3 混合结构

Lua 允许将数组与 key-value 混合在同一个 table 中进行定义。key-value 不会占用数组的数字索引值。

4.1.4 table操作函数

Lua中提供了对table进行操作的函数;

table.concat()
# 该函数用于将指定的 table 数组元素进行字符串连接。
# 连接从 start 索引位置到 end 索引位置的所有数组元素, 元素间使用指定的分隔符 sep 隔开。
# 这个连接与 key-value 无关,仅是连接数组元素;table.unpack()
# 该函数返回指定 table 的数组中的从第 i 个元素到第 j 个元素值
# i 与 j 是可选的,默认 i 为 1,j 为数组的最后一个元素table.pack()
# 该函数的参数是一个可变参,其可将指定的参数打包为一个 table 返回
# 返回的 table 中具有一个属性 n,用于表示该 table 包含的元素个数table.maxn()
# 该函数返回指定 table 的数组中的最大索引值,即数组包含元素的个数table.insert()
# 该函数用于在指定 table 的数组部分指定位置 pos 插入值为 value 的一个元素
# 其后的元素会被后移。pos 参数可选,默认为数组部分末尾;table.remove()
# 该函数用于删除并返回指定 table 中数组部分位于 pos 位置的元素
# 其后的元素会被前移。pos 参数可选,默认删除数组中的最后一个元素table.sort()
# 该函数用于对指定的 table 的数组元素进行升序排序
# 也可按照指定函数 fun(a,b) 中指定的规则进行排序
# fun(a,b)是一个用于比较 a 与 b 的函数,a 与 b 分别代表数组中的两个相邻元素# 如果 arr 中的元素既有字符串又有数值型,那么对其进行排序会报错
# 如果数组中多个元素相同,则其相同的多个元素的排序结果不确定,即这些元素的索引谁排前谁排后,不确定
# 如果数组元素中包含 nil,则排序会报错

4.2 迭代器

Lua 提供了两个迭代器 pairs(table)ipairs(table)。这两个迭代器通常会应用于泛型 for 循环中,用于遍历指定的 table

ipars(table):仅会迭代指定 table 中的数组元素;
pairs(table):迭代整个 table 元素,无论是数组元素,还是 key-value;

4.3 模块

模块是 Lua中特有的一种数据结构。Lua加入了标准的模块管理机制,可以把一些公用的代码放在一个文件里,以API接口的形式在其他地方调用,有利于代码的重用和降低代码耦合度;

模块文件主要由table组成,在table中添加相应的变量、函数,最后文件返回该table即可。只需要通过require将该模块导入即可;

4.3.1 定义一个模块

模块是一个 lua 文件,其中会包含一个 table

4.3.2 使用模块

require(“文件路径”),其中文件名是不能写.lua 扩展名的。

该函数可以将指定的 lua 文件静态导入(合并为一个文件);

该函数的使用可以省略小括号,写为 require “文件路径

require()函数是有返回值的,返回的就是模块文件最后 return table。可以使用一个变量接收该 table 值作为模块的别名;

4.3.3 再看模块

模块文件中一般定义的变量与函数都是模块 table 相关内容,但也可以定义其它与 table 无关的内容。

这些全局变量与函数就是普通的全局变量与函数,与模块无关,但会随着模块的导入而同时导入。

4.4 元表与元方法

元表,即 Lua 中普通 table 的元数据表,而元方法则是元表中定义的普通表的默认行为。

Lua 中的每个普通 table 都可为其定义一个元表,用于扩展该普通 table 的行为功能。

4.4.1 重要函数

setmetatable(table, metatable):将metatable指定为普通表table的元表;getmetatable(table):获取指定普通表 table 的元表;

4.4.2 __index元方法

当用户在对 table 进行读取访问时,如果访问的数组索引或 key 不存在,那么系统就会自动调用元表的_ _index 元方法。

该重写的方法可以是一个函数,也可以是另一个表。

如果重写的_ _index 元方法是函数,且有返回值,则直接返回;如果没有返回值,则返回 nil

nil
通过【x】访问的值不存在
通过【2】访问的值不存在

depart
西安

4.4.3 __newindex元方法

当用户为 table 中一个不存在的索引或 key 赋值时,就会自动调用元表的_ _newindex 元方法。该重写的方法可以是一个函数,也可以是另一个表。如果重写的_ _newindex 元方法是函数,且有返回值,则直接返回;如果没有返回值,则返回 nil

depart新增的key为x value为天津天津

nil
天津# emp.x = "天津"触发元表的__newindex,数据存入other表,故print(other.x)输出天津

4.4.4 运算符元方法

如果要为一个表扩展加号(+)、减号(-)、等于(==)、小于(<)等运算功能,则可重写相应的元方法。 

例如,如果要为一个 table 扩展加号(+)运算功能,则可重写该 table 元表的_ _add 元方法,而具体的运算规则,则是定义在该重写的元方法中的。这样,当一个 table 在进行加法(+)运算时,就会自动调用其元表的_ _add 元方法。 

1	北京5
2	张三5
3	28
4	上海5
5	销售部5
6	广州5
7	17
8	深圳5
name	张三5
age	28
depart	销售部5

4.4.5 __toString元方法

直接输出一个 table,其输出的内容为类型与 table 的存放地址

如果想让其输出 table 中的内容,可重写_ _tostring 元方法。

1:北京 name:张三 age:23 2:上海 depart:销售部 3:广州 4:12 5:深圳 
1:北京5 name:张三5 age:28 2:上海5 depart:销售部5 3:广州5 4:17 5:深圳5 

4.4.6 __call元方法

当将一个 table 以函数形式来使用时,系统会自动调用重写的_ _call 元方法。

该用法主要是可以简化对 table 的相关操作,将对 table 的操作与函数直接相结合。

1	北京hello
2	张三hello
3	28
4	上海hello
5	销售部hello
6	64
7	广州hello
8	深圳hello
name	张三hello
age	    28
depart	销售部hello

4.4.7 元表单独定义

为了便于管理与复用,可以将元素单独定义为一个文件。

该文件中仅可定义一个元表,且一般文件名与元表名称相同。 

若一个文件要使用其它文件中定义的元表,只需使用 require “元表文件名即可将元表导入使用。 

4.5 面向对象

Lua 中没有类的概念,但通过 tablefunction 与元表可以模拟和构造出具有类这样功能的结构。

4.5.1 简单对象的创建

Lua 中通过 table fcuntion 可以创建出一个简单的 Lua 对象:table Lua 对象赋予属性,通过 function Lua 对象赋予行为,即方法。

4.5.2 类的创建

Lua 中使用 tablefunction 与元表可以定义出类:使用一个表作为基础类,使用一个 function 作为该基础类的 new()方法。在该 new()方法中创建一个空表,再为该空表指定一个元表。

该元表重写_ _index 元方法,且将基础表指定为重写的_ _index 元方法。由于 new() 中的表是空表,所以用户访问的所有 key 都会从基础类(表)中查找。

带参构造器

4.6 协同线程与协同函数

Lua 中有一种特殊的线程,称为 coroutine,协同线程,简称协程。其可以在运行时暂停执行,然后转去执行其它线程,然后还可返回再继续执行没有执行完毕的内容。即可以“走走停停,停停再走走”。

协同线程也称为协作多线程,在 Lua 中表示独立的执行线程。任意时刻只会有一个协程执行,而不会出现多个协程同时执行的情况。

协同线程的类型为 thread,其启动、暂停、重启等,都需要通过函数来控制。下表是用于控制协同线程的基本方法。

4.6.1 协同函数

协同线程可以单独创建执行,也可以通过协同函数的调用启动执行。

使用 coroutine wrap()函数创建的就是协同函数,其类型为 function

由于协同函数的本质就是函数,所以协同函数的调用方式就是标准的函数调用方式。

只不过,协同函数的调用会启动其内置的协同线程。

-- 创建一个协同函数
cf = coroutine.wrap(function (a, b)print(a, b)-- 获取当前协同函数创建的协同线程tr = coroutine.running()print("tr的类型为:" .. type(tr))-- 挂起当前的协同线程coroutine.yield(a+1, b+1)print("又重新返回到了协同线程")return a+b, a*bend
)-- 调用协同函数,启动协同线程
result1, result2 = cf(3, 5)
print(result1, result2)        
# 3 5
# tr的类型为: thread
# 4 6print("cf的类型为:" .. type(cf))    # cf的类型为: function-- 重启挂起的协同线程
result1, result2 = cf(3, 5)
print(result1, result2)
# 又重新返回到了协同线程
# 8 15

4.7 文件IO

Lua 中提供了大量对文件进行 IO 操作的函数。这些函数分为两类:静态函数与实例函数。

所谓静态函数是指通过 io.xxx()方式对文件进行操作的函数,而实例函数则是通过 Lua 中面向对象方式操作的函数。

4.7.1 常用IO静态函数

4.7.2 常用实例函数


file.seek()

http://www.dtcms.com/a/511303.html

相关文章:

  • 【Block总结】ESSamp,下采样|保留原始图像信息|即插即用
  • 政务服务中心 网站建设html代码模板免费
  • Java日志收集技术
  • Gartner发布2026年十大战略技术趋势
  • 2025无人机在农业生态中的应用实践
  • 在 UOS(统信操作系统,基于 Debian/Ubuntu 体系)上编译 OpenCV 4.10.0
  • High-quality Surface Reconstruction using Gaussian Surfels 论文阅读
  • 百度地图多维检索:自然语言理解的深度搜索实践
  • 软件下载网站地址网站建设好了怎么进行推广
  • 牛客:NC16783拼数
  • UV技术:高效杀菌与精准固化的未来之光
  • PB级数据洪流下的抉择:从大数据架构师视角,深度解析时序数据库选型与性能优化(聚焦Apache IoTDB)
  • 时序数据库TDengine用法
  • 重庆市建设网站公司经济师考试时间2023报名时间
  • 第3章,[标签 Win32] :窗口类06,实例句柄与图标光标
  • 带你了解STM32:PWR电源控制
  • React Hooks完全指南
  • 多线程之ThreadLocal
  • 如何修改root密码
  • (三)React技术核心思想——组件化编程
  • 国外唯美flash个人网站欣赏建设网银
  • 【NVIDIA-H200-3】3节点all-reduce-三节点扩展的性能边界:NVIDIA H200 24 卡集群 all-reduce 通信效率深度剖析
  • D026 vue3+django 论文知识图谱推荐可视化系统 | vue3+vite前端|neo4j 图数据库
  • 桃浦做网站常德经开区网站官网
  • ODOO数据文件(XML、CSV、SQL)是如何转换并加载到 Odoo 数据库
  • ArcGIS JSAPI 学习教程 - 要素图层(FeatureLayer)分类、分组设置可视化样式(ClassBreaksRenderer)
  • 10天!前端用coze,后端用Trae IDE+Claude Code从0开始构建到平台上线
  • [JavaEE初阶] 传输层协议---UDP 相关笔记
  • 考研408《操作系统》复习笔记,第二章《2.3 进程调度》
  • 网站开发流程有哪几个阶段网站关键词多少个合适