Lua脚本学习
创始人
2025-06-01 01:28:59
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完成秒杀系统

相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
JAVA多线程知识整理 Java多线程基础 线程的创建和启动 继承Thread类来创建并启动 自定义Thread类的子类&#...
【洛谷 P1090】[NOIP... [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G ...
国民技术LPUART介绍 低功耗通用异步接收器(LPUART) 简介 低功耗通用异步收发器...
城乡供水一体化平台-助力乡村振... 城乡供水一体化管理系统建设方案 城乡供水一体化管理系统是运用云计算、大数据等信息化手段࿰...
程序的循环结构和random库...   第三个参数就是步长     引入文件时记得指明字符格式,否则读入不了 ...
中国版ChatGPT在哪些方面... 目录 一、中国巨大的市场需求 二、中国企业加速创新 三、中国的人工智能发展 四、企业愿景的推进 五、...
报名开启 | 共赴一场 Flu... 2023 年 1 月 25 日,Flutter Forward 大会在肯尼亚首都内罗毕...
汇编00-MASM 和 Vis... Qt源码解析 索引 汇编逆向--- MASM 和 Visual Studio入门 前提知识ÿ...
【简陋Web应用3】实现人脸比... 文章目录🍉 前情提要🌷 效果演示🥝 实现过程1. u...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
windows安装JDK步骤 一、 下载JDK安装包 下载地址:https://www.oracle.com/jav...
分治法实现合并排序(归并排序)... 🎊【数据结构与算法】专题正在持续更新中,各种数据结构的创建原理与运用✨...
在linux上安装配置node... 目录前言1,关于nodejs2,配置环境变量3,总结 前言...
Linux学习之端口、网络协议... 端口:设备与外界通讯交流的出口 网络协议:   网络协议是指计算机通信网...
Linux内核进程管理并发同步... 并发同步并发 是指在某一时间段内能够处理多个任务的能力,而 并行 是指同一时间能够处理...
opencv学习-HOG LO... 目录1. HOG(Histogram of Oriented Gradients,方向梯度直方图)1...
EEG微状态的功能意义 导读大脑的瞬时全局功能状态反映在其电场结构上。聚类分析方法一致地提取了四种头表面脑电场结构ÿ...
【Unity 手写PBR】Bu... 写在前面 前期积累: GAMES101作业7提高-实现微表面模型你需要了解的知识 【技...