视频:【动力节点】Redis入门到高级教程,全网最新最全redis缓存教程,redis百科大全
链接:https://pan.baidu.com/s/1VwGnpdP_JxYNWrPTPvMolg
提取码:810c
Lua是一个由标准C语言开发的、开源的、可扩展的、轻量级的、弱类型的、解释型脚本语言。
若要使用Lua则需要先从官网下载其源码并安装。
先将下载好的Lua源码上传到Linux,然后再进行安装。
将Lua源码解压到/opt/apps目录。
进入到/opt/apps下的lua目录可以看到编译用的Makefile文件及源码目录src。
由于Lua是由C/C++语言编写的,所以对其进行编译就必须要使用相关编译器。对于C/C++语言的编译器,使用最多的是gcc。
安装完毕后,可以通过lua –v查看版本号,与前面make linux test中最后显示的结果是相同的。
Lua为用户提供了两种交互模式:命令行模式与脚本文件模式。
该模式是,直接在命令行中输入语句,回车即可看到运行结果。
在任意目录下使用lua命令进入lua命令行模式,在其中输入语句后回车即可运行显示出结果。使用Ctrl + C退出模式。
需要注意,lua对语句后的分号要求不是强制性的,有没有都行。
该模式是先要编写脚本文件,然后再使用lua命令来运行文件。
例如,在当前用户主目录中新建一个script目录,在其中创建一个名称为hello.lua的文件,文件中就写一名print()语句即可。
然后直接运行“lua 脚本文件”即可看到结果。
对于脚本文件的运行有两种方式。一种是上面的lua命令方式,还有一种是可执行文件方式。可执行文件方式是,将lua脚本文件直接修改为可执行文件运行。
下面就使用第二种方式来运行。
在脚本文件第一行增加#!/usr/bin/lua,表示当前文件将使用/usr/bin/lua命令来运行。
这里要安装的是在Windows系统中Lua的运行环境。最常用的为SciTE。
SciTE是一款Lua脚本测试编辑器,提供Lua的编辑运行环境。SciTE提供了两种运行方式:命令行窗口运行方式与Lua脚本的编辑运行环境。
除了SciTE,还有像LuaDist、LuaRocks等。
Lua的行注释为两个连续的减号,段注释以--[[开头,以--]]结尾。
不过,在调试过程中如果想临时取消段注释,而直接将其标识删除,这样做其实并不好。因为有可能还需要再添加上。而段注释的写法相对较麻烦。所以,Lua给出了一种简单处理方式:在开头的–[[前再加一个减号,即可使段注释不起作用。其实就是使两个段注释标识变为了两个行注释。
Lua 中有 8 种类型,分别为:nil、boolean、number、string、userdata、function、thread 和 table。通过type()函数可以查看一个数据的类型,例如,type(nil)的结果为nil,type(123)的结果为number。
数据类型 | 描述 |
---|---|
nil | 只有值nil属于该类,表示一个无效值,与Java中的null类似。但在条件表达式中相当于false。 |
boolean | 包含两个值:false和true。 |
number | 表示双精度类型的实浮点数。 |
string | 字符串,由一对双引号或单引号括起来。当一个字符串包含多行时,可以在第一行中以[[开头,在最后一行中以]]结尾,那么在[[与]]括起来的这多行内容就是一个字符串。换行符为字符串”\n”。 |
table | 类似于Java中的数组,但比数组的功能更强大,更灵活。 |
function | 由 C 或 Lua 编写的函数。 |
thread | 协同线程,是协同函数的执行体,即正在执行的协同函数。 |
userdata | 一种用户自定义数据,用于表示一种由应用程序或 C/C++ 语言库所创建的类型,可以将任意 C/C++ 的任意数据类型的数据存储到 Lua 变量中调用。 |
程序设计语言中的标识符主要包含保留字、变量、常量、方法名、函数名、类名等。Lua的标识符由字母、数字与下划线组成,但不能以数字开头。Lua是大小写敏感的。
Lua常见的保留字共有22个。不过,除了这22个外,Lua中还定义了很多的内置全局变量,这些内置全局变量的一个共同特征是,以下划线开头后跟全大写字母。所以我们在定义自己的标识符时不能与这些保留字、内置全局变量重复。
and | break | do | else |
---|---|---|---|
elseif | end | false | for |
function | if | in | local |
nil | not | or | repeat |
return | then | true | until |
while | goto |
Lua是弱类型语言,变量无需类型声明即可直接使用。变量分为全局变量与局部变量。Lua中的变量默认都是全局变量,即使声明在语句块或函数里。全局变量一旦声明,在当前文件中的任何地方都可访问。局部变量local相当于Java中的private变量,只能在声明的语句块中使用。
Lua是动态类型语言,变量的类型可以随时改变,无需声明。
运算符是一个特殊的符号,用于告诉解释器执行特定的数学或逻辑运算。Lua提供了以下几种运算符类型:
下表列出了 Lua 语言中的常用算术运算符,设定 A 的值为10,B 的值为 20:
操作符 | 描述 | 示例 |
---|---|---|
+ | 加法 | A + B 输出结果 30 |
- | 减法 | A - B 输出结果 -10 |
* | 乘法 | A * B 输出结果 200 |
/ | 除法 | 5 / 2 输出结果 2.5 |
% | 取余 | B % A 输出结果 0 |
^ | 乘幂 | A^2 输出结果 100 |
- | 负号 | -A 输出结果 -10 |
// | 整除运算符(>=lua5.3) | 5//2 输出结果 2 |
下表列出了 Lua 语言中的常用关系运算符,设定 A 的值为10,B 的值为 20:
操作符 | 描述 | 示例 |
---|---|---|
== | 等于 | (A == B) 为 false。 |
~= | 不等于 | (A ~= B) 为 true。 |
> | 大于 | (A > B) 为 false。 |
< | 小于 | (A < B) 为 true。 |
>= | 大于等于 | (A >= B) 返回 false。 |
<= | 小于等于 | (A <= B) 返回 true。 |
注意,Lua系统将false与nil作为假,将true与非nil作为真,即使是0也是真。
下表列出了 Lua 语言中的常用逻辑运算符,设定 A 的值为 true,B 的值为 false:
操作符 | 描述 | 示例 |
---|---|---|
and | 逻辑与 | (A and B) 为 false。 |
or | 逻辑或 | (A or B) 为 true。 |
not | 逻辑非 | not(A and B) 为 true。 |
下表列出了 Lua 语言中的连接运算符与计算表或字符串长度的运算符:
操作符 | 描述 | 示例 |
---|---|---|
… | ||
(两个点) | 字符串连接符。 | a…b ,其中 a 为 "Hello " , b 为 “World”, 输出结果为 “Hello World”。 |
# | 返回字符串或表的长度。 | #“Hello” 返回 5。 |
Lua中函数的定义是以function开头,后跟函数名与参数列表,以end结尾。其可以没有返回值,也可以一次返回多个值。
Lua中的函数在调用时与Java语言中方法的调用是不同的,其不要求实参的个数必须与函数中形参的个数相同。如果实参个数少于形参个数,则系统自动使用nil填充;如果实参个数多于形参个数,多出的将被系统自动忽略。
在函数定义时不给出具体形参的个数,而是使用三个连续的点号。在函数调用时就可以向该函数传递任意个数的参数,函数可以全部接收。
Lua中的函数一次可以返回多个值,但需要有多个变量来同时接收。
Lua的函数中,允许函数作为参数。而作为参数的函数,可以是已经定义好的普通函数,也可以是匿名函数。
Lua提供了if作为流程控制语句。
Lua提供了if…then用于表示条件判断,其中if的判断条件可以是任意表达式。Lua系统将false与nil作为假,将true与非nil作为真,即使是0也是真。
需要注意,Lua中的if语句的判断条件可以使用小括号括起来,也可以不使用。
Lua中提供了专门的关键字elseif来做if嵌套语句。注意,不能使用else与if两个关键字的联用形式,即不能使用else if来嵌套if语句。
Lua提供了四种循环控制语句:while…do循环、repeat…until循环、数值for循环,及泛型for循环。同时,Lua还提供了break与goto两种循环流程控制语句。
只要while中的条件成立就一直循环。
until中的条件成立了,循环就要停止。
这种for循环只参用于循环变量为数值型的情况。其语法格式为:
for var=exp1, exp2, exp3 do
循环体
end
var为指定的循环变量,exp1为循环起始值,exp2为循环结束值,exp3为循环步长。步长可省略不写,默认为1。每循环一次,系统内部都会做一次当前循环变量var的值与exp2的比较,如果var小于等于exp2的值,则继续循环,否则结束循环。
泛型for用于遍历table中的所有值,其需要与Lua的迭代器联合使用。后面table学习时再详解。
break语句可以提前终止循环。其只能用于循环之中。
goto语句可以将执行流程无条件地跳转到指定的标记语句处开始执行,注意,是开始执行,并非仅执行这一句,而是从这句开始后面的语句都会重新执行。当然,该标识语句在第一次经过时也是会执行的,并非是必须由goto跳转时才执行。
语句标记使用一对双冒号括起来,置于语句前面。goto语句可以使用在循环之外。
注意,Lua5.1中不支持双冒号的语句标记。
使用table可以定义一维、二维、多维数组。不过,需要注意,Lua中的数组索引是从1开始的,且无需声明数组长度,可以随时增加元素。当然,同一数组中的元素可以是任意类型。
使用table也可以定义出类似map的key-value数据结构。其可以定义table时直接指定key-value,也可单独指定key-value。而访问时,一般都是通过table的key直接访问,也可以数组索引方式来访问,此时的key即为索引。
Lua允许将数组与key-value混合在同一个table中进行定义。key-value不会占用数组的数字索引值。
Lua中提供了对table进行操作的函数。
【函数】table.concat (table [, sep [, start [, end]]]):
【解析】该函数用于将指定的table数组元素进行字符串连接。连接从start索引位置到end索引位置的所有数组元素, 元素间使用指定的分隔符sep隔开。如果table是一个混合结构,那么这个连接与key-value无关,仅是连接数组元素。
【函数】table.unpack (table [, i [, j]])
【解析】拆包。该函数返回指定table的数组中的从第i个元素到第j个元素值。i与j是可选的,默认i为1,j为数组的最后一个元素。Lua5.1不支持该函数。
【函数】table.pack (…)
【解析】打包。该函数的参数是一个可变参,其可将指定的参数打包为一个table返回。这个返回的table中具有一个属性n,用于表示该table包含的元素个数。Lua5.1不支持该函数。
【函数】table.maxn(table)
【解析】该函数返回指定table的数组中的最大索引值,即数组包含元素的个数。
【函数】table.insert (table, [pos,] value):
【解析】该函数用于在指定table的数组部分指定位置pos插入值为value的一个元素。其后的元素会被后移。pos参数可选,默认为数组部分末尾。
【函数】table.remove (table [, pos])
【解析】该函数用于删除并返回指定table中数组部分位于pos位置的元素。其后的元素会被前移。pos参数可选,默认删除数组中的最后一个元素。
【函数】table.sort(table [,fun(a,b)])
【解析】该函数用于对指定的table的数组元素进行升序排序,也可按照指定函数fun(a,b)中指定的规则进行排序。fun(a,b)是一个用于比较a与b的函数,a与b分别代表数组中的两个相邻元素。
注意:
Lua提供了两个迭代器pairs(table)与ipairs(table)。这两个迭代器通常会应用于泛型for循环中,用于遍历指定的table。这两个迭代器的不同是:
模块是Lua中特有的一种数据结构。从 Lua 5.1 开始,Lua 加入了标准的模块管理机制,可以把一些公用的代码放在一个文件里,以 API 接口的形式在其他地方调用,有利于代码的重用和降低代码耦合度。
模块文件主要由table组成。在table中添加相应的变量、函数,最后文件返回该table即可。如果其它文件中需要使用该模块,只需通过require将该模块导入即可。
模块是一个lua文件,其中会包含一个table。一般情况下该文件名与该table名称相同,但其并不是必须的。
这里要用到一个函数require(“文件路径”),其中文件名是不能写.lua扩展名的。该函数可以将指定的lua文件静态导入(合并为一个文件)。不过需要注意的是,该函数的使用可以省略小括号,写为require “文件路径”。
require()函数是有返回值的,返回的就是模块文件最后return的table。可以使用一个变量接收该table值作为模块的别名,就可以使用别名来访问模块了。
模块文件中一般定义的变量与函数都是模块table相关内容,但也可以定义其它与table无关的内容。这些全局变量与函数就是普通的全局变量与函数,与模块无关,但会随着模块的导入而同时导入。所以在使用时可以直接使用,而无需也不能添加模块名称。
元表,即Lua中普通table的元数据表,而元方法则是元表中定义的普通表的默认行为。Lua中的每个普通table都可为其定义一个元表,用于扩展该普通table的行为功能。例如,对于table与数值相加的行为,Lua中是没有定义的,但用户可通过为其指定元表来扩展这种行为;再如,用户访问不存在的table元素,Lua默认返回的是nil,但用户可能并不知道发生了什么。此时可以通过为该table指定元表来扩展该行为:给用户提示信息,并返回用户指定的值。
元表中有两个重要函数:
当用户在对table进行读取访问时,如果访问的数组索引或key不存在,那么系统就会自动调用元表的_ index元方法。该重写的方法可以是一个函数,也可以是另一个表。如果重写的 _index元方法是函数,且有返回值,则直接返回;如果没有返回值,则返回nil。
当用户为table中一个不存在的索引或key赋值时,就会自动调用元表的_ newindex元方法。该重写的方法可以是一个函数,也可以是另一个表。如果重写的 _newindex元方法是函数,且有返回值,则直接返回;如果没有返回值,则返回nil。
如果要为一个表扩展加号(+)、减号(-)、等于(==)、小于(<)等运算功能,则可重写相应的元方法。
例如,如果要为一个table扩展加号(+)运算功能,则可重写该table元表的_ add元方法,而具体的运算规则,则是定义在该重写的元方法中的。这样,当一个table在进行加法(+)运算时,就会自动调用其元表的 _add元方法。
类似于加法操作的其它操作,Lua中还包含很多:
元方法 | 说明 | 元方法 | 说明 | |
---|---|---|---|---|
__add | 加法,+ | __band | 按位与,& | |
__sub | 减法,- | __bor | 按位或,| | |
__mul | 乘法,* | __bxor | 按位异或,~ | |
__div | 除法,/ | __bnot | 按位非,~ | |
__mod | 取模,% | __shl | 按位左移,<< | |
__pow | 次幂,^ | __shr | 按位右移,>> | |
__unm | 取反,- | |||
__idiv | 取整除法,// | __eq | 等于,== | |
__lt | 小于,< | |||
__concat | 字符串连接,… | __le | 小于等于,<= | |
__len | 字符串长度,# |
直接输出一个table,其输出的内容为类型与table的存放地址。如果想让其输出table中的内容,可重写_ _tostring元方法。
当将一个table以函数形式来使用时,系统会自动调用重写的_ _call元方法。该用法主要是可以简化对table的相关操作,将对table的操作与函数直接相结合。
为了便于管理与复用,可以将元素单独定义为一个文件。该文件中仅可定义一个元表,且一般文件名与元表名称相同。
若一个文件要使用其它文件中定义的元表,只需使用require “元表文件名”即可将元表导入使用。
如果用户想扩展该元表而又不想修改元表文件,则可在用户自己文件中重写其相应功能的元方法即可。
Lua中没有类的概念,但通过table、function与元表可以模拟和构造出具有类这样功能的结构。
Lua中通过table与fcuntion可以创建出一个简单的Lua对象:table为Lua对象赋予属性,通过function为Lua对象赋予行为,即方法。
Lua中使用table、function与元表可以定义出类:使用一个表作为基础类,使用一个function作为该基础类的new()方法。在该new()方法中创建一个空表,再为该空表指定一个元表。该元表重写_ index元方法,且将基础表指定为重写的 _index元方法。由于new()中的表是空表,所以用户访问的所有key都会从基础类(表)中查找。
Lua中有一种特殊的线程,称为coroutine,协同线程,简称协程。其可以在运行时暂停执行,然后转去执行其它线程,然后还可返回再继续执行没有执行完毕的内容。即可以“走走停停,停停再走走”。
协同线程也称为协作多线程,在Lua中表示独立的执行线程。任意时刻只会有一个协程执行,而不会出现多个协程同时执行的情况。
协同线程的类型为thread,其启动、暂停、重启等,都需要通过函数来控制。下表是用于控制协同线程的基本方法。
方法 | 描述 |
---|---|
create(function) | 创建一个协同线程实例,即返回的是thread类型。参数是一个function。其需要通过resume()来启动协同线程的执行 |
resume(thread, …) | 启动指定的协同线程的执行,使其从开始处或前面挂起处开始执行。可以向create()的内置函数传递相应的参数。如果内置函数具有返回值,resume()会全部接收并返回。 |
running() | 返回正在运行的协同线程实例,即thread类型值 |
yield() | 挂起协同线程,并将协同线程设置为挂起状态。resume()可从挂起处重启被挂起的协同线程 |
status(thread) | 查看协同线程的状态。状态有三种:运行态running,挂起态suspended,消亡态dead |
close() | 关闭协同线程 |
wrap(function) | 创建一个协同函数,返回的是function类型。一旦调用该函数就会创建并执行一个协同线程实例 |
协同线程可以单独创建执行,也可以通过协同函数的调用启动执行。使用coroutine的wrap()函数创建的就是协同函数,其类型为function。
由于协同函数的本质就是函数,所以协同函数的调用方式就是标准的函数调用方式。只不过,协同函数的调用会启动其内置的协同线程。
Lua中提供了大量对文件进行IO操作的函数。这些函数分为两类:静态函数与实例函数。所谓静态函数是指通过io.xxx()方式对文件进行操作的函数,而实例函数则是通过Lua中面向对象方式操作的函数。
【格式】io.open (filename [, mode])
【解析】以指定模式打开指定文件,返回要打开文件的句柄,就是一个对象(后面会讲Lua中的对象)。其中模式mode有三种,但同时还可配合两个符号使用:
【格式】io.input (file)
【解析】指定要读取的文件。
【格式】io.output (file)
【解析】指定要写入的文件。
【格式】io.read([format])
【解析】以指定格式读取io.input()中指定的输入文件。其中format格式有:
【格式】io.write(data)
【解析】将指定的数据data写入到io.output()中指定的输出文件。
这里的file使用的是io.open()函数返回的file,其实际就是Lua中的一个对象。其用法与io.read()的相同。
用法与io.write()的相同。
【格式】file:seek ([whence [, offset]])
【解析】该函数用于获取或设置文件读写指针的当前位置。位置从1开始计数,除文件最后一行外,每行都有行结束符,其会占两个字符位置。位置0表示文件第一个位置的前面位置。
当seek()为无参时会返回读写指针的当前位置。参数whence的值有三种,表示将指针定位的不同位置。而offset则表示相对于whence指定位置的偏移量,offset的默认值为0,为正表示向后偏移,为负表示向前偏移。