Lua脚本学习
创始人
2025-06-01 02:38:36
0

1、介绍

Lua 是一个小巧的脚本语言。其设计目的是为了通过灵活嵌入应用程序中从而为应用程序提供灵活的扩展和定制功能。Lua由标准C编写而成,几乎在所有操作系统和平台上都可以编译,运行。Lua并没有提供强大的库,这是由它的定位决定的。所以Lua不适合作为开发独立应用程序的语言。
Lua脚本可以很容易的被C/C++ 代码调用,也可以反过来调用C/C++的函数,这使得Lua在应用程序中可以被广泛应用。 在所有脚本引擎中,Lua的速度是最快的。这一切都决定了Lua是作为嵌入式脚本的最佳选择。

2、运行环境安装(linux版)

下载lua源码包

wget http://www.lua.org/ftp/lua-5.4.0.tar.gz

解压文件

tar zxf lua-5.4.0.tar.gz

进入解压后的文件中,编译文件

make linux test

编译成功后,会在src目录里面看到lua.c和luac.c文件

安装lua

make install

刷新动态库链接

ldconfig

验证是否安装成功

lua -v

3、lua的使用

基础语法

命名规则

lua中变量的命名规则和Java类似,可以由大小写字母、数字、下划线组成,但不能以数字开头,并且lua的内置关键字不能命名为变量

ab
ab12
_ab
ab_12
aA
AB

内置关键字

and

break

if

then

elseif

else

end

while

do

false

true

function

local

return

repeat

until

in

or

not

nil

goto

for

分号使用

lua语句的结尾,分号的使用是可选的

a = 1;
b = 2;c = 3
d = 4

注释规则

单行注释:两个连续的减号为单行注释

多行注释:两个连续减号,再加上两对方括号(注意:多行注释两个连续的--后面不能跟空格,否则会被认为是单行注释)

-- 此行为注释内容

a = 1

--[[

多行注释内容

]]

b = 2

全局变量和局部变量

在lua中使用local修饰的变量为局部变量,其它的变量都为全局变量

-- 全局变量i
i = 10;
do-- 局部变量xlocal x = i - 1;i = i - 1;-- 局部代码块打印xprint(x);
end
-- 打印i
print(i);
-- 局部代码块之外打印x
print(x);

可以看到x第一次正常打印出来了,x第二次打印的却是nil,这是因为x是局部变量,到外界被释放了

判断语句

--语法
if 表达式1 then
语句块1
elseif 表达式2 then
语句块2
else
语句块3
end
function panduan(a)if(a>100 or a<0) thenprint("输入不合法,请重新输入");elseif(a>=80) thenprint("优秀");elseif(a>=60) thenprint("及格");elseprint("不及格");end
end
print("please enter a number:");
n=io.read("*n");
panduan(n);

循环语句

--语法一
while 循环条件(符合该循环条件则继续循环) do
循环体
end
--语法二
repeat
循环体
until 循环条件(符合该循环条件,则退出循环)
--语法三
for 变量=初始值,终止值,步长 do
循环体
end
function whiletest(n,sum)local i = 0;while i<=n dosum=sum+i;i=i+1;endreturn sum;
end
function fortest(n,sum)for i=0,n,1 dosum=sum+i;endreturn sum;
end
function repeattest(n,sum)local i = 0;repeat sum=sum+i;i=i+1;until i>nreturn sum;
end
print("Please enter a number:");
n=io.read("*n");
print("while:add from 1 to "..n.." and the result is: "..whiletest(n,0));
print("for:add from 1 to "..n.." and the result is: "..fortest(n,0));
print("repeat:add from 1 to "..n.." and the result is: "..repeattest(n,0));

数据类型

lua有8种数据类型

分别为:nil(空),boolean(布尔),number(数值),string(字符串),userdata(用户数据),function(函数),thread(协程),table(表)

使用type()函数可以获取到值的类型名称

nil

nil是一种只有nil值的空类型,lua使用nil来表示无效值的情况,表示未被定义

boolean

boolean类型只有两个值:true和false

逻辑运算符

nil默认为false
and: 前面的操作数如果为false,就返回前面的操作数;否者返回后面的操作数
or: 前面的操作数为true,则返回前面的操作数,否者返回后面的
not: 取反

number

lua支持整型以及双精度的浮点型,整型被称为integer,浮点型被称为float,可以使用math.type()查看当前数值是类型

lua支持:加(+)、减(-)、乘(*)、除(/)、取负(-)、取模(%)、取整除(//)、幂运算(^)

注意:进行运行的时候,只有运算符号前后两个操作数都是整型并且不是除法时,结果才是整型,否则就是浮点型

lua对运算还提供了math数学库,与Java中的Math类似,可以对数据进行各种运算

例子:红包分配算法
t={}
function initAmount(m,n)local a = math.random(1,2*(math.floor(m/n)));if n>1 and m

string

lua中使用双引号或单引号来定义字符串变量,比如 a = "abc"或b = 'def'

并且b='def"abc"',单引号中包含双引号也可以正常输出,双引号不需要转义

但双引号中包含双引号,无法正常输出,这时候的双引号需要转义

字符串的相关操作

  • #后面跟上字符串,会返回当前字符串的长度

  • 字符串使用..进行拼接,如果拼接的是数值,会自动将其转为字符串

  • 多行字符串使用两对中括号包裹,a=[[字符串]],注意,使用该方式,如果字符串中有转义字符,无法转义

  • lua提供了数值和字符串的自动转换,在运算时,如果运算式中包含字符串,会自动尝试将其转为数值类型,转换不了,会报错(注意:比较运算符不会强制类型转换,因此当比较符前后同时包含数值和字符串时,会报错)

  • 显式类型转换,lua提供了主动的类型转换,tonumber(字符串)将字符串转为数值,tostring(数值)将数值转为字符串

  • lua提供了一个字符串库string,提供了很多功能处理字符串,调用示例:string.len(字符串)或字符串:len()

function

function类型定义的代码块,为函数区,可以通过函数名进行调用

--语法
function 函数名(入参1,入参2,...)具体代码
end
--调用方式
函数名(参数1,参数2,...)

table

表是lua中常用的一直数据结构,可以用来表示数组、集合等等

  • 使用a = {}构造表a,直接输出a会返回表的地址,a只是表的引用

  • 表添加元素采用的是a[key] = value,key-value的方式

  • 当多个表名引用同一张表时,任何一个引用改变了表数据,其它引用的表数据也会改变

  • 当表的所有引用都被释放时,垃圾回收器才会删除这张表

  • 将nil给表元素,可以将表元素删除

  • 当key是字符串时,可以通过表名.key名=value的方式插入数据,可以使用表名.key名的方式调用表元素等价于表名[key名]

  • a[0]和a["0"]是两个不一样的表元素,因为key一个是数值类型一个是字符串类型;但a[1]和a[1.0]指代的是同一个元素,因为整型和浮点型之间会进行类型转换,a[1.0]会转化成a[1]

  • 表的构建方法有:空构建,列表式构建,记录式构建,列表和记录混合构建

-- 表构建,相当于list={[1]="a",[2]="b",[3]="c",[4]="d",[5]="e",[6]="f"}
list={"a","b","c","d","e","f"}
-- 记录构建,相当于entity={["id"]=1,["name"]="zhangsan",["age"]=23}
entity={id=1,name="zhangsan",age=23}
-- 混合构建,相当于mix={["id"]=2,[1]="a",[2]="b",["name"]="lisi",["age"]=23,[3]="c"}
mix={id=2,"a","b",name="lisi",age=23,"c"}
print("list:first element is "..list[1]);
print("entity:name is "..entity.name);
print("mix:first element is "..mix[1].." name is "..mix.name);
  • pairs迭代器和ipairs迭代器

table={1,2,3,id="10021","a","b",name="ls"}
print("pairs result is:");
-- pairs可以遍历出所有的元素,但是遍历的元素不是按顺序的
for k,v in pairs(table) doprint(k,v);
end
print("ipairs result is:")
--[[ipairs只能遍历序列(key从1开始,直到key不连续为止),
输出顺序会按定义的顺序输出]]
for k,v in ipairs(table) doprint(k,v)
end
  • table表标准库

t={1,2,3,4}
-- 在表t开头插入9,其它元素依次后移一位
table.insert(t,1,9);
print("insert(t,1,9)");
for k,v in pairs(t) doprint(k,v)
end
-- 在表t末尾插入10
table.insert(t,10);
print("insert(t,10)");
for k,v in pairs(t) doprint(k,v)
end
-- 移除表t第一个元素,其它元素依次前移一位
table.remove(t,1);
print("remove(t,1)");
for k,v in pairs(t) doprint(k,v)
end
-- 移除表t最后一位元素
table.remove(t);
print("remove(t)")
for k,v in pairs(t) doprint(k,v)
end

userdata

userdata叫做用户数据也叫用户自定义数据,其作用是为了与其它编程语言(例如C语言、C++、C#)进行交互。

thread

lua中的thread叫做协同程序,与线程比较类似,拥有独立的堆栈,独立的局部变量,独立的指令指针。

线程与协同程序的主要区别在于,一个具有多个线程的程序可以同时运行几个线程,而协同程序却需要彼此协作的运行。在任一指定时刻只有一个协同程序在运行,并且这个正在运行的协同程序只有在明确的被要求挂起的时候才会被挂起。线程是操作系统进行调度的最小单位,而协程则是在应用程序内部进行调度的最小单位。在多线程并发编程中,线程之间的切换涉及到内核态和用户态之间的切换,会带来一定的开销。而在协程并发编程中,由于很多协程都运行在同一个线程内,因此协程之间的切换只涉及到用户态之间的切换,避免了内核态和用户态之间的频繁切换,从而提高了性能

  • coroutine.create创建一个协程,返回的是corontine,参数是一个函数

  • coroutine.resume重新启动协程,配合create使用

  • coroutine.yield挂起协程

  • coroutine.status返回当前协程状态,suspended(挂起)、running(运行)、dead(死亡)

  • coroutine.wrap创建一个协程,返回一个函数,一旦调用这个函数,就会进入coroutine,和create类似。

  • coroutine.running返回正在运行的coroutine,返回的是coroutine的线程号

function run(data)-- 当前协程状态print("1:"..coroutine.status(co));data = data+1;print("co", 1, data);-- 当前协程的线程号print(coroutine.running());-- 当前协程挂起coroutine.yield()print("2:"..coroutine.status(co));print(coroutine.running())data = data+1;print("co", 2, data)
end
function test(data)-- 当前协程的线程号print(coroutine.running())data = data+1;print("co2",3,data)-- 协程挂起coroutine.yield()print(coroutine.running())data = data+1;print("co2",4,data)
end
print("coroutine.create():");
-- create方式创建协程
co = coroutine.create(run);
print("create status is:"..coroutine.status(co));
print("coroutine.wrap():");
-- wrap方式创建协程
co2 = coroutine.wrap(test);
--print("wrap status is:"..coroutine.status(co2));
data = 1
-- 启动co协程
coroutine.resume(co, data)
-- 启动co2协程
co2(data);
print("co first resume end status:"..coroutine.status(co));
print("main", data);
-- 重新启动co协程
coroutine.resume(co, data)
print("co second resume end status:"..coroutine.status(co));
-- 启动死亡协程,会报出cannot resume dead coroutine
print("co third resume:",coroutine.resume(co,data));
-- 重新启动co2协程
co2(data);

本章内容到此结束,下一章Redis运行Lua脚本和Redis配合Lua完成秒杀系统

相关内容

热门资讯

【MySQL】锁 锁 文章目录锁全局锁表级锁表锁元数据锁(MDL)意向锁AUTO-INC锁...
【内网安全】 隧道搭建穿透上线... 文章目录内网穿透-Ngrok-入门-上线1、服务端配置:2、客户端连接服务端ÿ...
GCN的几种模型复现笔记 引言 本篇笔记紧接上文,主要是上一篇看写了快2w字,再去接入代码感觉有点...
数据分页展示逻辑 import java.util.Arrays;import java.util.List;impo...
Redis为什么选择单线程?R... 目录专栏导读一、Redis版本迭代二、Redis4.0之前为什么一直采用单线程?三、R...
【已解决】ERROR: Cou... 正确指令: pip install pyyaml
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
Lock 接口解读 前置知识点Synchronized synchronized 是 Java 中的关键字,...
Win7 专业版安装中文包、汉... 参考资料:http://www.metsky.com/archives/350.htm...
3 ROS1通讯编程提高(1) 3 ROS1通讯编程提高3.1 使用VS Code编译ROS13.1.1 VS Code的安装和配置...
大模型未来趋势 大模型是人工智能领域的重要发展趋势之一,未来有着广阔的应用前景和发展空间。以下是大模型未来的趋势和展...
python实战应用讲解-【n... 目录 如何在Python中计算残余的平方和 方法1:使用其Base公式 方法2:使用statsmod...
学习u-boot 需要了解的m... 一、常用函数 1. origin 函数 origin 函数的返回值就是变量来源。使用格式如下...
常用python爬虫库介绍与简... 通用 urllib -网络库(stdlib)。 requests -网络库。 grab – 网络库&...
药品批准文号查询|药融云-中国... 药品批文是国家食品药品监督管理局(NMPA)对药品的审评和批准的证明文件...
【2023-03-22】SRS... 【2023-03-22】SRS推流搭配FFmpeg实现目标检测 说明: 外侧测试使用SRS播放器测...
有限元三角形单元的等效节点力 文章目录前言一、重新复习一下有限元三角形单元的理论1、三角形单元的形函数(Nÿ...
初级算法-哈希表 主要记录算法和数据结构学习笔记,新的一年更上一层楼! 初级算法-哈希表...
进程间通信【Linux】 1. 进程间通信 1.1 什么是进程间通信 在 Linux 系统中,进程间通信...
【Docker】P3 Dock... Docker数据卷、宿主机与挂载数据卷的概念及作用挂载宿主机配置数据卷挂载操作示例一个容器挂载多个目...