三、通用命令&lua脚本

一、通用命令

(一)key通用命令

key是一个字符串,通过key获取redis中保存的数据

1、key设计操作

  • 对于ky自身状态的相关操作,例如:别除,判定存在,获取类型等
  • 对于ky有效性控制相关操作,例如:有效期设定,判定是否有效,有效状态的切换等
  • 对于key快速查询操作,例如:按指定策略查询key

2、key 基本操作

  • 删除指定key

    del key

  • 获取key是否存在

    exists key

  • 获取key的类型

    type key

  • 根据规则查询key

    keys pattern

    • 查询模式规则:

    * 匹配任意数量的任意符号

    ?配合一个任意符号
    [] 匹配一个指定符号

    keys * 查询所有
    keys it* 查询所有以it开头
    keys *heima 查询所有以heima结尾
    keys ??heima 查询所有前面两个字符任意,后面以heima结尾
    keys user: ? 查询所有以user:开头,最后一个字符任意
    keys u[st]er:1 查询所有以u开头,以er:1结尾,中间包含一个字母,s或t

3、key 扩展操作

  • 为key指定有效期

    expire key seconds 设置秒级存活时间

pexpire key milliseconds 设置毫秒级存活时

expireat key timestamp 设置时间戳存活时间

pexpireat key milliseconds-timestamp

  • 获取key的有效期

    ttl key 如果key存在就返回-1,如果key不存在就返回-2,如果key设置了有效期就返回有效时长
    pttl key 如果key存在就返回-1,如果key不存在就返回-2,如果key设置了有效期就返回有效时长

  • 切换key从时效性转换为永久性

    persist key

  • 为key改名

    rename key newkey

    ​ 注意:如果将要更改的newkey,已经另外存在,就会把key的value覆盖到已经存在的key的值。

    renamenx key newkey 如果将要更改的newkey不存在,就把key更改,建议用这个。

  • 对所有key进行排序

    sort key desc/ase limit

​ 对原来的key进行排序,并不会更改原来的数据

  • 其他key通用操作

    help @generic

(二)数据库通用命令

1、key的重复问题

  • key是由程序员定义的
  • redis在使用过程中,伴随着操作数据量的增加,会出现大量的数据以及对应的ky
  • 数据不区分种类、类别混杂在一起,极易出现重复或冲突
解决方案:
  • redis为每个服务提供有16个数据库,编号从0到15
  • 每个数据库之间的数据相互独立

2、DB的基本操作

  • 切换数据库

select index

  • 退出客户端

quit

  • 测试服务器是否联通

ping

  • 输出日志

echo message

  • 数据移动:

​ move key db 将当前数据库下的key移动到指定的数据库

  • 查询当前数据库的所有key

    dbsize

  • 清空当前数据库的所有数据

    flushdb

  • 清空所有数据库的所有数据

    flushall

二、lua脚本

(一)Lua脚本初识

  • Redis调用Lua脚本通过eval命令保证代码执行的原子性,直接用return:返回脚本执行后的结果
    • eval luascript numkeys [key [key …][arg [arg …]
    • eval命令 lua脚本 传入key值的数量 传入key1值 key2值 传入value1值 value2值
  • Hello world
    • EVAL “return ‘hello lua’” 0
  • 切记lua脚本的下标从1开始

示例:

EVAL  "redis.call('set',k1',v1') redis.call('expire','k1','30')
return redis.call('get',k1')" 0
EVAL "return redis.call('mset' ,KEYS[1],ARGV[1],KEYS[2],ARGV[2]) 2 name1 name2 zhangsan1 lisi2

(二)环境安装

1、Linux环境安装

1.1源码安装

下载源码安装:

curl -L -R -O https://www.lua.org/ftp/lua-5.4.7.tar.gz
tar zxf lua-5.4.7.tar.gz
cd lua-5.4.7
make all test
make install
1.2使用包管理器安装

Debian/Ubuntu 系统:

sudo apt update
sudo apt install lua5.3

CentOS/RHEL 系统:

sudo yum install epel-release
sudo yum install lua

2、Window 系统上安装 Lua

window 下你可以使用一个叫 “SciTE” 的 IDE环 境来执行 lua 程序,下载地址为:

(三)Lua基本语法

1 交互式编程

Lua 提供了交互式编程模式。我们可以在命令行中输入程序并立即查看效果。

Lua 交互式编程模式可以通过命令 lua -i 或 lua 来启用:

$ lua -i 
$ Lua 5.3.0  Copyright (C) 1994-2015 Lua.org, PUC-Rio
> 

2 脚本式编程

我们可以将 Lua 程序代码保存到一个以 lua 结尾的文件,并执行,该模式称为脚本式编程,如我们将如下代码存储在名为 hello.lua 的脚本文件中:

print("Hello World!")
print("www.小Ti.com")

使用 lua 名执行以上脚本,输出结果为:

$ lua hello.lua
Hello World!
www.小Ti.com

3 注释

3.1 单行注释

单行注释以两个连字符 -- 开头,后面跟随的内容将被解释器忽略。

--

单行注释通常用于对代码的简短解释或标记。

3.2 多行注释

多行注释以 --[[ 开始,并以 ]] 结束,适用于需要对大段代码进行说明的情况。

--[[
 多行注释
 多行注释
 --]]

Lua 不支持嵌套注释,这意味着在一个多行注释内不能再嵌套另一个多行注释。例如,以下代码是不合法的:

--[[
这是一个多行注释
--[[
嵌套的多行注释(这是非法的)
]]
]]

(四) Lua数据类型

Lua 是动态类型语言,变量不要类型定义,只需要为变量赋值。 值可以存储在变量中,作为参数传递或结果返回。

Lua 中有 8 个基本类型分别为:nil、boolean、number、string、userdata、function、thread 和 table。

数据类型描述
nil这个最简单,只有值nil属于该类,表示一个无效值(在条件表达式中相当于false)。
boolean包含两个值:false和true。
number表示双精度类型的实浮点数
string字符串由一对双引号或单引号来表示
function由 C 或 Lua 编写的函数
userdata表示任意存储在变量中的C数据结构
thread表示执行的独立线路,用于执行协同程序
tableLua 中的表(table)其实是一个"关联数组"(associative arrays),数组的索引可以是数字、字符串或表类型。在 Lua 里,table 的创建是通过"构造表达式"来完成,最简单构造表达式是{},用来创建一个空表。

我们可以使用 type 函数测试给定变量或者值的类型:

实例

print(type("Hello world"))    *--> string*
print(type(10.4*3))       *--> number*
print(type(print))        *--> function*
print(type(type))        *--> function*
print(type(true))        *--> boolean*
print(type(nil))         *--> nil*
print(type(type(X)))       *--> string*

(五) Lua 循环

很多情况下我们需要做一些有规律性的重复操作,因此在程序中就需要重复执行某些语句。

一组被重复执行的语句称之为循环体,能否继续重复,决定循环的终止条件。

循环结构是在一定条件下反复执行某段程序的流程结构,被反复执行的程序被称为循环体。

循环语句是由循环体及循环的终止条件两部分组成的。

Lua 语言提供了以下几种循环处理方式:

循环类型描述
while 循环在条件为 true 时,让程序重复地执行某些语句。执行语句前会先检查条件是否为 true。
for 循环重复执行指定语句,重复次数可在 for 语句中控制。
repeat…until重复执行循环,直到 指定的条件为真时为止
循环嵌套可以在循环内嵌套一个或多个循环语句(while do … end;for … do … end;repeat … until;)

1、循环控制语句

循环控制语句用于控制程序的流程, 以实现程序的各种结构方式。

Lua 支持以下循环控制语句:

控制语句描述
break 语句退出当前循环或语句,并开始脚本执行紧接着的语句。
goto 语句将程序的控制点转移到一个标签处。

2、无限循环

在循环体中如果条件永远为 true 循环语句就会永远执行下去,以下以 while 循环为例:

实例

while( true )
do
  print("循环将永远执行下去")
end

(六)Lua 流程控制

Lua 编程语言流程控制语句通过程序设定一个或多个条件语句来设定。在条件为 true 时执行指定程序代码,在条件为 false 时执行其他指定代码。

Lua 编程语言流程控制语句通过程序设定一个或多个条件语句来设定。在条件为 true 时执行指定程序代码,在条件为 false 时执行其他指定代码。

控制结构的条件表达式结果可以是任何值,Lua认为false和nil为假,true和非nil为真。

要注意的是Lua中 0 为 true:

[ 0true ]
if(0)
then
  print("0 为 true")
end

Lua 提供了以下控制结构语句:

语句描述
if 语句if 语句 由一个布尔表达式作为条件判断,其后紧跟其他语句组成。
if…else 语句if 语句 可以与 else 语句搭配使用, 在 if 条件表达式为 false 时执行 else 语句代码。
if 嵌套语句你可以在ifelse if中使用一个或多个 ifelse if 语句 。

(七)Lua 函数

在Lua中,函数是对语句和表达式进行抽象的主要方法。既可以用来处理一些特殊的工作,也可以用来计算一些值。

Lua 提供了许多的内建函数,你可以很方便的在程序中调用它们,如print()函数可以将传入的参数打印在控制台上。

Lua 函数主要有两种用途:

  • 1.完成指定的任务,这种情况下函数作为调用语句使用;
  • 2.计算并返回值,这种情况下函数作为赋值语句的表达式使用。

Lua 编程语言函数定义格式如下:

optional_function_scope function function_name( argument1, argument2, argument3..., argumentn)
    function_body
    return result_params_comma_separated
end

解析:

  • optional_function_scope: 该参数是可选的指定函数是全局函数还是局部函数,未设置该参数默认为全局函数,如果你需要设置函数为局部函数需要使用关键字 local
  • function_name: 指定函数名称。
  • argument1, argument2, argument3…, argumentn: 函数参数,多个参数以逗号隔开,函数也可以不带参数。
  • function_body: 函数体,函数中需要执行的代码语句块。
  • result_params_comma_separated: 函数返回值,Lua语言函数可以返回多个值,每个值以逗号隔开。
--[[ 函数返回两个值的最大值 --]]
function max(num1, num2)

   if (num1 > num2) then
      result = num1;
   else
      result = num2;
   end

   return result;
end
-- 调用函数
print("两值比较最大值为 ",max(10,4))
print("两值比较最大值为 ",max(5,6))

(八)Lua 运算符

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

  • 算术运算符
  • 关系运算符
  • 逻辑运算符
  • 其他运算符

1、算术运算符

下表列出了 Lua 语言中的常用算术运算符,设定 A 的值为10,B 的值为 20:

操作符描述实例
+加法A + B 输出结果 30
-减法A - B 输出结果 -10
*乘法A * B 输出结果 200
/除法B / A 输出结果 2
%取余B % A 输出结果 0
^乘幂A^2 输出结果 100
-负号-A 输出结果 -10
//整除运算符(>=lua5.3)5//2 输出结果 2
a = 21
b = 10
c = a + b
print("Line 1 - c 的值为 ", c )
c = a - b
print("Line 2 - c 的值为 ", c )
c = a * b
print("Line 3 - c 的值为 ", c )
c = a / b
print("Line 4 - c 的值为 ", c )
c = a % b
print("Line 5 - c 的值为 ", c )
c = a^2
print("Line 6 - c 的值为 ", c )
c = -a
print("Line 7 - c 的值为 ", c )

以上程序执行结果为:

Line 1 - c 的值为     31
Line 2 - c 的值为     11
Line 3 - c 的值为     210
Line 4 - c 的值为     2.1
Line 5 - c 的值为     1
Line 6 - c 的值为     441
Line 7 - c 的值为     -21

2、关系运算符

下表列出了 Lua 语言中的常用关系运算符,设定 A 的值为10,B 的值为 20:

操作符描述实例
==等于,检测两个值是否相等,相等返回 true,否则返回 false(A == B) 为 false。
~=不等于,检测两个值是否相等,不相等返回 true,否则返回 false(A ~= B) 为 true。
>大于,如果左边的值大于右边的值,返回 true,否则返回 false(A > B) 为 false。
<小于,如果左边的值大于右边的值,返回 false,否则返回 true(A < B) 为 true。
>=大于等于,如果左边的值大于等于右边的值,返回 true,否则返回 false(A >= B) 返回 false。
<=小于等于, 如果左边的值小于等于右边的值,返回 true,否则返回 false(A <= B) 返回 true。
a = 21
b = 10

if( a == b )
then
   print("Line 1 - a 等于 b" )
else
   print("Line 1 - a 不等于 b" )
end

if( a ~= b )
then
   print("Line 2 - a 不等于 b" )
else
   print("Line 2 - a 等于 b" )
end

if ( a < b )
then
   print("Line 3 - a 小于 b" )
else
   print("Line 3 - a 大于等于 b" )
end

if ( a > b ) 
then
   print("Line 4 - a 大于 b" )
else
   print("Line 5 - a 小于等于 b" )
end

-- 修改 a 和 b 的值
a = 5
b = 20
if ( a <= b ) 
then
   print("Line 5 - a 小于等于  b" )
end

if ( b >= a ) 
then
   print("Line 6 - b 大于等于 a" )
end

(九)Lua 字符串

字符串或串(String)是由数字、字母、下划线组成的一串字符。

在 Lua 中,字符串是一种基本的数据类型,用于存储文本数据。

Lua 中的字符串可以包含任意字符,包括字母、数字、符号、空格以及其他特殊字符。

string1 = "Lua"
print("\"字符串 1 是\"",string1)
string2 = '小Ti.com'
print("字符串 2 是",string2)

string3 = [["Lua 教程"]]
print("字符串 3 是",string3)

以上代码执行输出结果为:

"字符串 1 是"    Lua
字符串 2 是    小Ti.com
字符串 3 是    "Lua 教程"

字符串长度计算

在 Lua 中,要计算字符串的长度(即字符串中字符的个数),你可以使用 string.len函数或 utf8.len 函数,包含中文的一般用 utf8.lenstring.len 函数用于计算只包含 ASCII 字符串的长度。

实例

`local myString = "Hello, 小Ti!"`

-- 计算字符串的长度(字符个数)
local length = string.len(myString)

print(length) -- 输出 14

以上实例的 myString 字符串只包含 ASCII 字符,因此 string.len 函数可以准确地返回字符串的长度。

包含中文的字符串使用 utf8.len函数:

实例

local myString = "Hello, 世界!"

-- 计算字符串的长度(字符个数)*
local length1 = utf8.len(myString)
print(length1) *-- 输出 10*

-- string.len 函数会导致结果不准确*
local length2 = string.len(myString)
print(length2) *-- 输出 14*

1、字符串的操作

Lua 提供了很多的方法来支持字符串的操作:

序号方法 & 用途
1string.upper(argument): 字符串全部转为大写字母。
2string.lower(argument): 字符串全部转为小写字母。
3**string.gsub(mainString,findString,replaceString,num)**在字符串中替换。mainString 为要操作的字符串, findString 为被替换的字符,replaceString 要替换的字符,num 替换次数(可以忽略,则全部替换),如:> string.gsub("aaaa","a","z",3); zzza 3
4string.find (str, substr, [init, [plain]]) 在一个指定的目标字符串 str 中搜索指定的内容 substr,如果找到了一个匹配的子串,就会返回这个子串的起始索引和结束索引,不存在则返回 nil。init 指定了搜索的起始位置,默认为 1,可以一个负数,表示从后往前数的字符个数。plain 表示是否使用简单模式,默认为 false,true 只做简单的查找子串的操作,false 表示使用使用正则模式匹配。以下实例查找字符串 “Lua” 的起始索引和结束索引位置:> string.find("Hello Lua user", "Lua", 1) 7 9
5string.reverse(arg) 字符串反转> string.reverse("Lua") auL
6string.format(…) 返回一个类似printf的格式化字符串> string.format("the value is:%d",4) the value is:4
7string.char(arg) 和 string.byte(arg[,int]) char 将整型数字转成字符并连接, byte 转换字符为整数值(可以指定某个字符,默认第一个字符)。> string.char(97,98,99,100) abcd > string.byte("ABCD",4) 68 > string.byte("ABCD") 65 >
8string.len(arg) 计算字符串长度。string.len("abc") 3
9string.rep(string, n) 返回字符串string的n个拷贝> string.rep("abcd",2) abcdabcd
10 链接两个字符串> print("www.小Ti.".."com") www.小Ti.com
11string.gmatch(str, pattern) 返回一个迭代器函数,每一次调用这个函数,返回一个在字符串 str 找到的下一个符合 pattern 描述的子串。如果参数 pattern 描述的字符串没有找到,迭代函数返回nil。> for word in string.gmatch("Hello Lua user", "%a+") do print(word) end Hello Lua user
12string.match(str, pattern, init) string.match()只寻找源字串str中的第一个配对. 参数init可选, 指定搜寻过程的起点, 默认为1。 在成功配对时, 函数将返回配对表达式中的所有捕获结果; 如果没有设置捕获标记, 则返回整个配对字符串. 当没有成功的配对时, 返回nil。> = string.match("I have 2 questions for you.", "%d+ %a+") 2 questions > = string.format("%d, %q", string.match("I have 2 questions for you.", "(%d+) (%a+)")) 2, "questions"

2、字符串截取

字符串截取使用 sub() 方法。

string.sub() 用于截取字符串,原型为:

string.sub(s, i [, j])

参数说明:

  • s:要截取的字符串。
  • i:截取开始位置。
  • j:截取结束位置,默认为 -1,最后一个字符。

3、字符串大小写转换

string1 = "Lua";
print(string.upper(string1))
print(string.lower(string1))

4、字符串查找与反转

string = "Lua Tutorial"
-- 查找字符串
print(string.find(string,"Tutorial"))
reversedString = string.reverse(string)
print("新字符串为",reversedString)

5、字符串格式化

string1 = "Lua"
string2 = "Tutorial"
number1 = 10
number2 = 20
-- 基本字符串格式化
print(string.format("基本格式化 %s %s",string1,string2))
-- 日期格式化
date = 2; month = 1; year = 2014
print(string.format("日期格式化 %02d/%02d/%04d", date, month, year))
-- 十进制格式化
print(string.format("%.4f",1/3))
基本格式化 Lua Tutorial
日期格式化 02/01/2014
0.3333
string.format("%c", 83)                 -- 输出S
string.format("%+d", 17.0)              -- 输出+17
string.format("%05d", 17)               -- 输出00017
string.format("%o", 17)                 -- 输出21
string.format("%u", 3.14)               -- 输出3
string.format("%x", 13)                 -- 输出d
string.format("%X", 13)                 -- 输出D
string.format("%e", 1000)               -- 输出1.000000e+03
string.format("%E", 1000)               -- 输出1.000000E+03
string.format("%6.3f", 13)              -- 输出13.000
string.format("%q", "One\nTwo")         -- 输出"One\
                                        --   Two"
string.format("%s", "monkey")           -- 输出monkey
string.format("%10s", "monkey")         -- 输出    monkey
string.format("%5.3s", "monkey")        -- 输出  mon

6、字符与整数相互转换

-- 字符转换
-- 转换第一个字符
print(string.byte("Lua"))
-- 转换第三个字符
print(string.byte("Lua",3))
-- 转换末尾第一个字符
print(string.byte("Lua",-1))
-- 第二个字符
print(string.byte("Lua",2))
-- 转换末尾第二个字符
print(string.byte("Lua",-2))

-- 整数 ASCII 码转换为字符
print(string.char(97))
76
97
97
117
117
a

7、匹配模式

Lua 中的匹配模式直接用常规的字符串来描述。 它用于模式匹配函数 string.find, string.gmatch, string.gsub, string.match

你还可以在模式串中使用字符类。

字符类指可以匹配一个特定字符集合内任何字符的模式项。比如,字符类 %d 匹配任意数字。所以你可以使用模式串 %d%d/%d%d/%d%d%d%d 搜索 dd/mm/yyyy 格式的日期:

s = "Deadline is 30/05/1999, firm"
date = "%d%d/%d%d/%d%d%d%d"
print(string.sub(s, string.find(s, date)))    --> 30/05/1999

(十)Lua 数组

数组,就是相同数据类型的元素按一定顺序排列的集合,可以是一维数组和多维数组。

在 Lua 中,数组不是一种特定的数据类型,而是一种用来存储一组值的数据结构。

实际上,Lua 中并没有专门的数组类型,而是使用一种被称为 “table” 的数据结构来实现数组的功能。

Lua 数组的索引键值可以使用整数表示,数组的大小不是固定的。

在 Lua 索引值是以 1 为起始,但你也可以指定 0 开始。

1、一维数组

一维数组是最简单的数组,其逻辑结构是线性表。

-- 创建一个数组
local myArray = {10, 20, 30, 40, 50}

-- 访问数组元素
print(myArray[1])  -- 输出 10
print(myArray[3])  -- 输出 30

2、多维数组

多维数组即数组中包含数组或一维数组的索引键对应一个数组。

-- 初始化数组
array = {}
for i=1,3 do
   array[i] = {}
      for j=1,3 do
         array[i][j] = i*j
      end
end

-- 访问数组
for i=1,3 do
   for j=1,3 do
      print(array[i][j])
   end
end

(十一)Lua 迭代器

迭代器(iterator)是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址。

在 Lua 中迭代器是一种支持指针类型的结构,它可以遍历集合的每一个元素。

1、泛型 for 迭代器

泛型 for 在自己内部保存迭代函数,实际上它保存三个值:迭代函数、状态常量、控制变量。

泛型 for 迭代器提供了集合的 key/value 对,语法格式如下:

for k, v in pairs(t) do
    print(k, v)
end

2、无状态的迭代器

无状态的迭代器是指不保留任何状态的迭代器,因此在循环中我们可以利用无状态迭代器避免创建闭包花费额外的代价。

每一次迭代,迭代函数都是用两个变量(状态常量和控制变量)的值作为参数被调用,一个无状态的迭代器只利用这两个值可以获取下一个元素。

这种无状态迭代器的典型的简单的例子是 ipairs,它遍历数组的每一个元素,元素的索引需要是数值。

function square(iteratorMaxCount,currentNumber)
   if currentNumber<iteratorMaxCount
   then
      currentNumber = currentNumber+1
   return currentNumber, currentNumber*currentNumber
   end
end

for i,n in square,3,0
do
   print(i,n)
end

3、多状态的迭代器

很多情况下,迭代器需要保存多个状态信息而不是简单的状态常量和控制变量,最简单的方法是使用闭包,还有一种方法就是将所有的状态信息封装到 table 内,将 table 作为迭代器的状态常量,因为这种情况下可以将所有的信息存放在 table 内,所以迭代函数通常不需要第二个参数。


array = {"Google", "小Ti"}

function elementIterator (collection)
   local index = 0
   local count = #collection
   -- 闭包函数
   return function ()
      index = index + 1
      if index <= count
      then
         --  返回迭代器的当前元素
         return collection[index]
      end
   end
end

for element in elementIterator(array)
do
   print(element)
end

以上实例输出结果为:

Google
小Ti

nction square(iteratorMaxCount,currentNumber)
if currentNumber<iteratorMaxCount
then
currentNumber = currentNumber+1
return currentNumber, currentNumber*currentNumber
end
end

for i,n in square,3,0
do
print(i,n)
end

3、多状态的迭代器

很多情况下,迭代器需要保存多个状态信息而不是简单的状态常量和控制变量,最简单的方法是使用闭包,还有一种方法就是将所有的状态信息封装到 table 内,将 table 作为迭代器的状态常量,因为这种情况下可以将所有的信息存放在 table 内,所以迭代函数通常不需要第二个参数。

array = {"Google", "小Ti"}

function elementIterator (collection)
   local index = 0
   local count = #collection
   -- 闭包函数
   return function ()
      index = index + 1
      if index <= count
      then
         --  返回迭代器的当前元素
         return collection[index]
      end
   end
end

for element in elementIterator(array)
do
   print(element)
end

以上实例输出结果为:

Google
小Ti
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小Ti客栈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值