Nginx14-Lua基础

零、文章目录

Nginx14-Lua基础

  • Nginx是可扩展的,可用于处理各种使用场景。本节中,我们将探讨使用Lua扩展Nginx的功能。

1、简介

(1)概念
  • Lua是一种轻量、小巧的脚本语言,用标准C语言编写并以源代码形式开发。设计的目的是为了嵌入到其他应用程序中,从而为应用程序提供灵活的扩展和定制功能。
(2)特性
  • 跟其他语言进行比较,Lua有其自身的特点:

    • 轻量级:Lua用标准C语言编写并以源代码形式开发,编译后仅仅一百余千字节,可以很方便的嵌入到其他程序中。
    • 可扩展:Lua提供非常丰富易于使用的扩展接口和机制,由宿主语言(通常是C或C++)提供功能,Lua可以使用它们,就像内置的功能一样。
    • 支持面向过程编程和函数式编程
(3)应用场景
  • 游戏开发
  • 独立应用脚本
  • web应用脚本
  • 扩展和数据库插件
  • 系统安全上

2、Lua的安装

(1)下载地址
(2)安装
  • 在linux上安装Lua非常简单,只需要下载源码包并在终端解压、编译即可使用。
bash 复制代码
# 创建文件目录
mkdir /opt/lua
cd /opt/lua

# 下载
# 我们可以下载再上传服务器,也可以使用wget命令在服务器上直接下载
wget https://www.lua.org/ftp/lua-5.4.7.tar.gz

# 解压
tar -zxvf lua-5.4.7.tar.gz

# 编译安装
cd lua-5.4.7
make linux test
make install

# 验证是否安装成功
lua -v
  • 如果在执行make linux test失败,报系统缺少libreadline-dev依赖包,需要通过命令来进行安装
bash 复制代码
yum install -y readline-devel

3、Lua的语法

  • Lua和C/C++语法非常相似,整体上比较清晰,简洁。条件语句、循环语句、函数调用都与C/C++基本一致。如果对C/C++不太熟悉的同学来说,也没关系,因为天下语言是一家,基本上理解起来都不会太困难。我们一点点来讲。
(1)交互方式
  • Lua有两种交互方式

    • **交互式:**指可以在命令行输入程序,然后回车就可以看到运行的效果。
    • **脚本式:**脚本式是将代码保存到一个以 lua 为扩展名的文件中并执行的方式。
  • **交互式:**Lua交互式编程模式可以通过命令lua -i 或lua回车来进入Lua交互式环境,直接输入命令回车就可以看到效果,最后通过Ctrl+C可以退出交互环境。

bash 复制代码
[root@localhost lua-5.4.7]# lua
Lua 5.4.7  Copyright (C) 1994-2024 Lua.org, PUC-Rio
> print("hello world!")
hello world!
> ^C
  • **脚本式1:**将代码保存到一个以lua为扩展名的文件中,用lua hello.lua执行。
bash 复制代码
# 创建lua文件,文件写入命令
cd /opt/lua/lua-5.4.7/
vim hello.lua
print("hello world!")

# lua执行
[root@localhost lua]# lua hello.lua
hello world!
  • **脚本式2:**直接运行hello.lua文件

    • 将hello.lua做如下修改,第一行用来指定Lua解释器所在位置为 /usr/local/bin/lua,加上#号标记解释器会忽略它。一般情况下#!就是用来指定用哪个程序来运行本文件。
    lua 复制代码
    #!/usr/local/bin/lua
    print("Hello World!!!")
    • 但是hello.lua并不是一个可执行文件,需要通过chmod来设置可执行权限如下
    bash 复制代码
    chmod 755 hello.lua
    • 然后执行该文件
    bash 复制代码
    [root@localhost lua]# ./hello.lua
    Hello World!!!
  • **交互式中运行脚本:**如果想在交互式中运行脚本式的hello.lua中的内容,我们可以使用一个dofile函数

bash 复制代码
[root@localhost lua]# lua
Lua 5.4.7  Copyright (C) 1994-2024 Lua.org, PUC-Rio
> dofile("hello.lua")
Hello World!!!
(2)分隔符
  • 注意:在Lua语言中,连续语句之间的分隔符并不是必须的,也就是说后面不需要加分号,当然加上也不会报错,

  • 在Lua语言中,表达式之间的换行也起不到任何作用。如以下四个写法,其实都是等效的,不建议使用第四种方式,可读性太差。

lua 复制代码
写法一
a=1
b=a+2
写法二
a=1;
b=a+2;
写法三
a=1; b=a+2;
写法四
a=1 b=a+2
(3)注释
  • 关于Lua的注释要分两种,第一种是单行注释,第二种是多行注释。

  • 单行注释的语法为:

    --注释内容

  • 多行注释的语法为:

    --[[
    注释内容
    注释内容
    --]]

  • 如果想取消多行注释,只需要在第一个--之前在加一个-即可,如:

    ---[[
    注释内容
    注释内容
    --]]

(4)标识符
  • 换句话说标识符就是我们的变量名。
  • Lua定义变量名以一个字母 A 到 Z 或 a 到 z 或下划线 _ 开头后加上0个或多个字母,下划线,数字(0到9)。
  • 这块建议大家最好不要使用下划线加大写字母的标识符,因为Lua的保留字也是这样定义的,容易发生冲突。注意Lua是区分大小写字母的。
(5)关键字
  • 下列是Lua的关键字,大家在定义常量、变量或其他用户自定义标识符都要避免使用以下这些关键字:
and break do else
elseif end false for
function if in local
nil not or repeat
return then true until
while goto
  • 一般约定,以下划线开头连接一串大写字母的名字(比如 _VERSION)被保留用于 Lua 内部全局变量。这个也是上面我们不建议这么定义标识符的原因。
(6)运算符
  • Lua中支持的运算符有算术运算符、关系运算符、逻辑运算符、其他运算符。

  • 算术运算符

lua 复制代码
+   加法
-	减法
*	乘法
/	除法
%	取余
^	乘幂
-	负号

--案例如下
10+20	-->30
20-10	-->10
10*20	-->200
20/10	-->2
3%2		-->1
10^2	-->100
-10		-->-10
  • 关系运算符
lua 复制代码
==	等于
~=	不等于
>	大于
<	小于
>=	大于等于
<=	小于等于

--案例如下
10==10		-->true
10~=10		-->false
20>10		-->true
20<10		-->false
20>=10		-->true
20<=10		-->false
  • 逻辑运算符
lua 复制代码
and	逻辑与	 A and B     &&   
or	逻辑或	 A or B     ||
not	逻辑非  取反,如果为true,则返回false  !

--逻辑运算符可以作为if的判断条件,返回的结果如下
A = true
B = true

A and B	-->true
A or  B -->true
not A 	-->false

A = true
B = false

A and B	-->false
A or  B -->true
not A 	-->false

A = false
B = true

A and B	-->false
A or  B -->true
not A 	-->true
  • 其他运算符
lua 复制代码
..	连接两个字符串
#	一元预算法,返回字符串或表的长度

--案例如下
> "HELLO ".."WORLD"		-->HELLO WORLD
> #"HELLO"			-->5
(7)全局变量
  • 在Lua语言中,全局变量无须声明即可使用。在默认情况下,变量总是认为是全局的,如果未提前赋值,默认为nil:
bash 复制代码
[root@master lua-5.4.7]# lua
Lua 5.4.7  Copyright (C) 1994-2024 Lua.org, PUC-Rio
> print(b)
nil
> b=100
> print(b)
100
> b=nil
> print(b)
nil
(8)局部变量
  • 要想声明一个局部变量,需要使用local来声明,终端交互式的 local 声明的变量在同一行使用,换行了则离开了该变量的作用域。
bash 复制代码
[root@master lua-5.4.7]# lua
Lua 5.4.7  Copyright (C) 1994-2024 Lua.org, PUC-Rio
> local a=100
> print(a)
nil
> local a=100 print(a)
100

3、Lua数据类型

  • Lua有8个数据类型
lua 复制代码
nil(空,无效值)
boolean(布尔,true/false)
number(数值)
string(字符串)
function(函数)
table(表)
thread(线程)
userdata(用户数据)
  • 可以使用type函数测试给定变量或者的类型:
lua 复制代码
print(type(nil))				-->nil
print(type(true))               --> boolean
print(type(1.1*1.1))             --> number
print(type("Hello world"))      --> string
print(type(io.stdin))			-->userdata
print(type(print))              --> function
print(type(type))               -->function
print(type{})					-->table
print(type(type(X)))            --> string
(1)nil
  • nil是一种只有一个nil值的类型,它的作用可以用来与其他所有值进行区分
  • 想要移除一个变量时,只需要将该变量名赋值为nil,垃圾回收就会会释放该变量所占用的内存。
(2)boolean
  • boolean类型具有两个值,true和false。boolean类型一般被用来做条件判断的真与假。

  • 在Lua语言中,只会将false和nil视为假,其他的都视为真,特别是在条件检测中0和空字符串都会认为是真,这个和我们熟悉的大多数语言不太一样。

(3)number
  • 在Lua5.3版本开始,Lua语言为数值格式提供了两种选择integer(整型)和float(双精度浮点型),和其他语言不太一样,float不代表单精度类型。

  • 数值常量的表示方式:

lua 复制代码
>4			-->4
>0.4		-->0.4
>4.75e-3	-->0.00475
>4.75e3		-->4750
  • 不管是整型还是双精度浮点型,使用type()函数来取其类型,都会返回的是number,所以它们之间是可以相互转换的,同时,具有相同算术值的整型值和浮点型值在Lua语言中是相等的
lua 复制代码
>type(3)	-->number
>type(3.3)	-->number
(4)string
  • Lua语言中的字符串即可以表示单个字符,也可以表示一整本书籍。在Lua语言中,操作100K或者1M个字母组成的字符串的程序很常见。

  • 可以使用单引号或双引号来声明字符串。

lua 复制代码
>a = "hello"
>b = 'world'
>print(a)	-->hello
>print(b) 	-->world
  • 如果声明的字符串比较长或者有多行,则可以使用如下方式进行声明
lua 复制代码
html = [[
<html>
<head>
<title>Lua-string</title>
</head>
<body>
<a href="http://www.lua.org">Lua</a>
</body>
</html>
]]
(5)table
  • table是Lua语言中最主要和强大的数据结构。使用表, Lua 语言可以以一种简单、统一且高效的方式表示数组、集合、记录和其他很多数据结构。 Lua语言中的表本质上是一种辅助数组。这种数组比Java中的数组更加灵活,可以使用数值做索引,也可以使用字符串或其他任意类型的值作索引(除nil外)。

  • 创建表的最简单方式

lua 复制代码
> a = {}
  • 创建数组
lua 复制代码
--数组:就是相同数据类型的元素按照一定顺序排列的集合
--创建数组
>arr = {"TOM","JERRY","ROSE"}

--要想获取数组中的值,我们可以通过如下内容来获取
print(arr[0])		nil
print(arr[1])		TOM
print(arr[2])		JERRY
print(arr[3])		ROSE

--从上面的结果可以看出来,数组的下标默认是从1开始的。所以上述创建数组,也可以通过如下方式来创建
>arr = {}
>arr[1] = "TOM"
>arr[2] = "JERRY"
>arr[3] = "ROSE"

--上面我们说过了,表的索引即可以是数字,也可以是字符串等其他的内容,所以我们也可以将索引更改为字符串来创建
>arr = {}
>arr["X"] = 10
>arr["Y"] = 20
>arr["Z"] = 30

--当然,如果想要获取这些数组中的值,可以使用下面的方式
--方式一
>print(arr["X"])
>print(arr["Y"])
>print(arr["Z"])
--方式二
>print(arr.X)
>print(arr.Y)
>print(arr.Z)

--当前table的灵活不进于此,还有更灵活的声明方式
>arr = {"TOM",X=10,"JERRY",Y=20,"ROSE",Z=30}

--如何获取上面的值?
TOM :  arr[1]
10  :  arr["X"] | arr.X
JERRY: arr[2]
20  :  arr["Y"] | arr.Y
ROESE?
(6)function
  • 在 Lua语言中,函数( Function )是对语句和表达式进行抽象的主要方式。

  • 定义函数的语法为:

lua 复制代码
function functionName(params)

end
  • 函数被调用的时候,传入的参数个数与定义函数时使用的参数个数不一致的时候,Lua 语言会通过 抛弃多余参数和将不足的参数设为 nil 的方式来调整参数的个数。
lua 复制代码
function  f(a,b)
print(a,b)
end

f()		--> nil  nil
f(2)	--> 2 nil
f(2,6)	--> 2 6
f(2.6.8)	--> 2 6 (8被丢弃)
  • 可变长参数函数
lua 复制代码
function add(...)
a,b,c=...
print(a)
print(b)
print(c)
end

add(1,2,3)  --> 1 2 3
  • 函数返回值可以有多个,这点和Java不太一样
lua 复制代码
function f(a,b)
return a,b
end

x,y=f(11,22)	--> x=11,y=22	
(7)thread
  • thread翻译过来是线程的意思,在Lua中,thread用来表示执行的独立线路,用来执行协同程序。
lua 复制代码
-- 定义一个简单的协程函数
function simpleCoroutine()
    print("Coroutine started")
    coroutine.yield("Hello from coroutine!")
    print("Coroutine resumed")
end

-- 创建协程
local co = coroutine.create(simpleCoroutine)

-- 启动协程
local success, result = coroutine.resume(co)

-- 协程会打印 "Coroutine started" 然后暂停并返回结果
print("Main thread received: " .. result)  -- 打印从协程返回的消息

-- 再次启动协程,协程将继续执行直到结束
success, result = coroutine.resume(co)

-- 打印 "Coroutine resumed"
-- 由于协程已经结束,这里不会打印更多的信息
(8)userdata
  • userdata是一种用户自定义数据,用于表示一种由应用程序或C/C++语言库所创建的类型。

4、Lua控制结构

  • Lua 语言提供了一组精简且常用的控制结构,包括用于条件执行的then以及用于循环的 while、 repeat 和 for。
  • 所有的控制结构语法上都有一个显式的终结符: end 用于终结 if、 for 及 while 结构, until 用于终结 repeat 结构。
(1)if then else
  • if语句先测试其条件,并根据条件是否满足执行相应的 then 部分或 else 部分。 else 部分是可选的。
lua 复制代码
function testif(a)
 if a>0 then
 	print("a是正数")
 end
end

function testif(a)
 if a>0 then
 	print("a是正数")
 else
 	print("a是负数")
 end
end
  • 如果要编写嵌套的 if 语句,可以使用 elseif。 它类似于在 else 后面紧跟一个if。根据传入的年龄返回不同的结果,如
lua 复制代码
age<=18 青少年,
age>18 , age <=45 青年
age>45 , age<=60 中年人
age>60 老年人

function show(age)
if age<=18 then
 return "青少年"
elseif age>18 and age<=45 then
 return "青年"
elseif age>45 and age<=60 then
 return "中年人"
elseif age>60 then
 return "老年人"
end
end
(2)while循环
  • 顾名思义,当条件为真时 while 循环会重复执行其循环体。 Lua 语言先测试 while 语句 的条件,若条件为假则循环结束;否则, Lua 会执行循环体并不断地重复这个过程。

  • 语法:

lua 复制代码
while 条件 do
  循环体
end
  • 案例:实现数组的循环
lua 复制代码
function testWhile()
 local i = 1
 while i<=10 do
  print(i)
  i=i+1
 end
end
(3)repeat循环
  • 顾名思义, repeat-until语句会重复执行其循环体直到条件为真时结束。 由于条件测试在循环体之后执行,所以循环体至少会执行一次。

  • 语法:

lua 复制代码
repeat
 循环体
until 条件
  • 案例:
lua 复制代码
function testRepeat()
 local i = 10
 repeat
  print(i)
  i=i-1
 until i < 1
end
(4)for循环
  • 数值型for循环

  • 语法:

lua 复制代码
for param=exp1,exp2,exp3 do
 循环体
end
  • 案例:param的值从exp1变化到exp2之前的每次循环会执行循环体,并在每次循环结束后将步长(step)exp3增加到param上。exp3可选,如果不设置默认为1
lua 复制代码
for i = 1,100,10 do
print(i)
end

--输出结果
1
11
21
31
41
51
61
71
81
91
  • 泛型for循环:泛型for循环通过一个迭代器函数来遍历所有值,类似于java中的foreach语句。

  • 语法:

lua 复制代码
for i,v in ipairs(x) do
	循环体
end
  • 案例:i是数组索引值,v是对应索引的数组元素值,ipairs是Lua提供的一个迭代器函数,用来迭代数组,x是要遍历的数组。
lua 复制代码
arr = {"TOME","JERRY","ROWS","LUCY"}
for i,v in ipairs(arr) do
 print(i,v)
end

--输出结果
1	TOM
2	JERRY
3	ROWS
4	LUCY
  • 但是如果将arr的值进行修改,同样的代码在执行的时候,就只能看到和之前一样的结果,而其中的x为JACK就无法遍历出来
lua 复制代码
arr = {"TOME","JERRY","ROWS",x="JACK","LUCY"}
for i,v in ipairs(arr) do
 print(i,v)
end

--输出结果
1	TOM
2	JERRY
3	ROWS
4	LUCY
  • 我们可以将迭代器函数变成pairs,就能遍历出来了
lua 复制代码
for i,v in pairs(arr) do
 print(i,v)
end

--输出结果
1	TOM
2	JERRY
3	ROWS
4	LUCY
x	JACK
相关推荐
isyangli_blog5 小时前
OpenDayLight (Carbon 版本) 启动与组件安装
开发语言·php
vb2008116 小时前
FastAPI APIRouter
开发语言·python
Benszen6 小时前
KVM虚拟化解决方案
开发语言·perl
会编程的土豆6 小时前
Go 语言反射(Reflection)详解
开发语言·后端·golang
東雪木6 小时前
多线程与并发编程 专属复习笔记
java·开发语言·笔记·java面试
杨充6 小时前
1.3 浮点型数据设计灵魂
开发语言·python·算法
噜噜噜阿鲁~6 小时前
python学习笔记 | 11.3、面向对象高级编程-多重继承
java·开发语言
basketball6166 小时前
Go 语言从入门到进阶:4. 数组和MAP使用方法总结
开发语言·后端·golang
春生野草7 小时前
反射、Tomcat执行
java·开发语言
雪的季节8 小时前
企业级 Qt 全功能项目
开发语言·数据库·qt