Redis基础知识(学习笔记21--Lua 脚本语言)

1 Lua 简介

Lua 是一个由标准C语言开发的、开源的、可扩展的、轻量级的、弱类型的、解释型脚本语言,是于1993年由巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de Janeiro)的三人研究小组使用标准C语言开发。

官网:https://www.lua.org/

 2 安装

注意 源码安装时,需要先安装gcc-c++

yum - y install gcc-c++

 安装过程不在赘述

安装后,可以通过以下命令查询程序路径

whereis lua

3 语法基础

3.1 注释

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

3.2 数据类型

Lua 中有8种类型,分布为:nil、boolean、number、string、userdata、function、thread 和 table。通过type()函数可以查看一个数据的类型。

数据类型 描述
nil 只有值nil属于该类,表示一个无效值,与Java中的null类似。但在条件表达式中相当于false。
boolean 包含两个值:false和true。
number 表示双精度类型的实浮点数。
string 字符串,由一对双引号或单引号括起来。当一个字符串包含多行时,可以在第一行中以 [[ 开头,在最后一行中以  ]]  结尾,那么在 [[ 与 ]] 括起来的这多行内容就是一个字符串。换行符为字符串“\n”。
table 类似于Java中的数组,但比数组的功能更强大,更灵活。
function 由 C 或 Lua 编写的函数
thread 协同线程,是协同函数的执行体,即正在执行的协同函数。
userdata 一种用户自定义函数,用于表示一种由应用函数或C/C++语言库所创建的类型,可以将任意C/C++的任意数据类型的数据存储到Lua变量中调用。

3.3 标识符

标识符主要包含保留字、变量、常量、方法名、函数名、类名等。Lua的标识符由字母、数字与下划线组成,但不能以数字开头。Lua是大小写敏感的。

(1)保留字

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    

(2)变量

Lua是弱类型语言,变量不需类型声明即可直接使用。变量分为全局变量和局部变量。Lua中的变量默认都是全局变量,即使声明在语句块或函数里。全局变量一旦声明,在当前文件中的任何地方都可以访问。局部变量local相当于Java中的private变量,只能在声明的语句块中使用。

(3)动态类型

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

3.4 运算符

运算符是一种特殊的符号,用于告诉解释器执行特定的数学或者逻辑运算。Lua提供了以下几种运算符类型。

(1)算数运算符

设定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
// 整除运算符(>=lua 5.3) 5//2 输出结果 2

注意:

在 整除运算符 时,例如 5//2,可能会报错:

lua: a.lua: XXX : unexpected symbol near '/'  ---XXX 代表行号

报错原因时版本的问题。需要 >=lua 5.3。

 (2)关系运算符

设定A的值为10,B的值为20.

操作符 描述 示例
== 等于 (A==B)为false
~= 不等于  (A~=B) 为true
> 大于 (A>B)为false
< 小于 (A<B)为true
>= 大于等于 (A>=B)为false
<= 小于等于 (A<=B)为true

(3)逻辑运算符

注意:Lua系统将false 与 nil 作为假,将true 与非nul作为真,即使是0也为真。

设定A的值为true,B的值为false。

操作符 描述 示例
and 逻辑与 (A and B) 为false
or 逻辑或 (A or B) 为true
not 逻辑非 not (A and B) 为true

(4)其它运算符

操作符 描述 示例

..

(两个点)

字符串连接符

a..b,其中a为“Hello”,b为“ World”,

输出结果为“Hello World”。

# 返回字符串或表的长度 #Hello,输出结果为5。

3.5 函数

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

(1)固定函数

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

(2)可变参函数

在函数定义时不给出具体形参的个数,而是使用三个连续的点号。在函数调用时就可以向该函数传递任意个数的参数,函数可以全部接收。

(3)可返回多个值

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

(4)函数作为参数

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

3.6 流程控制语句

Lua提供了if作为流程控制语句

(1)if 语句

Lua 提供了if ... then 用于表示条件判断,其中if的判断条件可以是任意表达式。 Lua系统将false 与 nil 作为假,将true 与 非 nil 作为真,即使是0也是真。

需要注意,Lua中的if语句的判断条件可以使用小括号括起来,也可以不使用。

(2)if 嵌套语句

Lua中提供了专门的关键字elseif来做if嵌套语句。

注意,不能使用else 与 if 两个关键字的联用形式,即不能使用else if 来嵌套if语句。

3.7 循环控制语句

(1)While ... do

只要while 中的条件成立就一直循环。

(2)repeat ... until

until 中的条件成立了,循环就要停止了。

(3)数值for

这种for循环只,用于循环变量为数值型的情况。其语法格式为:

for var=exp1,exp2,exp3 do

exp2,为条件(exp2>=exp1);

exp3 ,为步长,省略不写时,默认为1。

(4)泛型for

泛型for用于遍历table中的所有值,其需要与Lua的迭代器联合使用。

(5)break 

break语句可以提前终止循环。其只能用于循环之中。

(6)goto

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

语句标识使用一对双冒号括起来,置于语句前面。goto语句可以在循环之外。

注意,Lua5.1 中不支持双冒号的语句标记。

 4 语法进阶

4.1 table

(1)数组

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

(2)map

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

 (3)混合结构

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

(4)table 操作函数

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

table.concat ()

【函数】table.concat (list [, sep [, start [, end]]])

【解析】该函数用于将指定的table数组进行字符串连接。连接从start索引位置到end索引位置的所有数组元素,元素间使用指定的分隔符sep隔开。如果table是一个混合结构,那么这个连接与key-value无关,仅是连接数组元素。

table.pack()

【函数】table.pack (···)

【解析】打包。该函数的参数是一个可变参,其可将指定的参数打包为一个table返回。这个返回的table中具有一个属性n,用于表示该table包含的元素个数。Lua5.1 不支持该函数。

table.unpack()

【函数】table.unpack (list [, i [, j]])

【解析】拆包。该函数返回指定table的数组中的从第 i 个元素到第 j 个元素值。 i 与 j是可选的,默认i为1,j为数组的最后一个元素。Lua5.1 不支持该函数。

table.maxn()

【函数】table.maxn(table)

【解析】该函数返回指定table的数组中的最大索引值,即数组包含元素的个数。

table.insert()

【函数】table.insert (list, [pos,] value)

【解析】该函数用于在指定table的数组部分指定位置pos插入值为value的一个元素。其后的元素会被后移。pos参数可选,默认为数组部分末尾。

table.remove()

【函数】table.remove (list [, pos])

【解析】该函数用于删除并返回指定table中数组部分位于pos位置的元素。其后的元素会被迁移。pos参数可选,默认删除数组中的最后一个元素。

table.sort()

【函数】table.sort (table [, fun(a,b)])

【解析】该函数用于对指定table的数组进行升序排序,也可以按照指定函数fun(a,b)中指定的规则进行排序。fun(a,b)是一个用于比较a与b的函数,a与b分别代表数组中的两个相邻元素。

注意;

  • 如果arr中的元素既有字符串又有数值型,那么对其进行排序会报错。
  • 如果数组中多个元素相同,则其相同的多个元素的排序结果不确定,即这些元素的索引谁排前排后,不确定。
  • 如果数组元素中包含nil,则排序会报错。

 

学习笔记--参阅特别声明

1.【Redis视频从入门到高级】

【https://www.bilibili.com/video/BV1U24y1y7jF?p=11&vd_source=0e347fbc6c2b049143afaa5a15abfc1c】