redis学习(八) Lua语法

Lua语法

数据类型

Lua是一个动态类型语言,一个变量可以存储任何类型的值。编写redis脚本会用到的类型

Lua常用数据类型
类型名 取值
空(nil) 空类型只包含一个值,即nil。nil表示空,所有没有赋值的变量或表的字段都是nil
布尔(boolean) 布尔类型包含true和false
数字(number) 整数和浮点数都是使用数字类型存储,如1、0.23、3.5e20等
字符串(string) 字符串类型可以存储字符串,且与redis的键值一样都是二进制安全的。字符串可以使用单引号或双引号表示,两个符号是相同的,比如'a'和"a",字符串中可以包含转义字符,如\n,\r等
表(table) 表类型是Lua语言中唯一的数据结构,既可以当数组有可以当字典,十分灵活
函数(function) 函数在Lua中是一等值(first-class-value),可以存储在变量中、作为函数的参数或返回结果

变量

Lua的变量分为全局变量和局部变量。全局变量无需声明就可以直接使用,默认为nil

a=1 --为全局变量赋值
print(b) --无需声明即可使用,默认是nil
a = nil --删除全局变量a的方法是将其赋值为nil。全局变量没有声明和未声明之分,只有非nil和nil区别

在redis脚本中不能使用全局变量,只允许使用局部变量以防止脚本之间的相互影响,声明局部变量的方法为local变量名

local c --声明一个局部变量c,默认值是nil
local d =1 --声明局部变量并赋值1
local e,f --同时声明多个局部变量

变量名必须是非数字开头,只能包含字母、数字和下划线,区分大小写。变量名不能和Lua的保留关键字相同,保留关键字如下:

and break do else elseif
end false for function if 
in local nil not or
repeat return then true until while

局部变量的作用域为从声明开始到所在层的语句块末尾,比如

local x =10
if true then 
local x = x+1 
print(x)
do
local x = x+1
print(x)
end 
print(x)
end 
print(x)

依次输出:

11 12 11 10

注释

单行注释以--开始,到行尾结束,一般习惯在--后面跟上一个空格

多行注释以--[[开始,到]]结束

赋值

Lua支持多重赋值,比如:

local a,b = 1,2 

local c,d = 1,2,2 -- c的值是1,d的值是2,3被舍弃了

local e,f = 1 -- e的值是1,f的值是nil

在执行多重赋值是,lua会先计算所有表达式的值,比如

local a = {1,2,3}

local i = 1

i,a[i] = i+1,5   变为 i,a[1] = 2,5  赋值后i为2, a则为{5,2,3}

操作符

Lua有以下5类操作符

1> 数学操作符。 + - * /  %(取模)  - (取负)  幂运算符 ^

print('1'+1) -- 2 数学操作符的操作数如果是字符串会自动转换为数字

2> 比较操作符 结果一定是boolean

redis学习(八) Lua语法_第1张图片

3>逻辑操作符

Lua逻辑操作符
操作符 说明
not 根据操作数的真和假相应地返回false和true
and a and b 中如果a为真则返回b,否则返回a
or  a  or b 如果 a 是true 则返回 a,否则返回b

只要操作数不是nil或false,逻辑操作符就认为操作符是真,否则是假。特别需要注意的是即使是0或者空字符串也被当做是真

print(1 and 5)  -- 5
print(1 or 5) -- 1
print(not 0) -- false
print('' or 1) -- ''

Lua的逻辑操作符支持短路,也就是说对于false and  foo() ,Lua不会去调用foo(),or 操作符类似

4> 连接操作符。 连接操作符只有一个 : ..,用来连接两个字符串,比如

print('hello'..''..'world') -- hello world 

连接操作符会自动把数字类型转为字符串类型

5> 取长度操作符。 #   例如 print(#'hello') -- 5 

            运算符的优先级(优先级依次降低)
		^
		not # - (一元)
		* / % 
		+ - 
		.. 
		< > <= >= ~= == 
		and 
		or

if语句

Lua的if语句格式如下:

if 条件表达式 then
   语句块
elseif 条件表达式 then
    语句块
else 语句块
end
note: 在Lua中只有nil和false才是假,其余值都是真,包括空字符串和0,都是认为是真的。这是一点容易出错的地方。

比如说:

if redis.call('exists','key') then 
   exists = true 
else 
    exists = false
end

这个exists返回的就是1或0,一定返回的是真,就有问题了,改为 if redis.call('exists','key') == 1 才正确

Lua与javascript每个语句都可以;结尾,都是省略的,当然也可以写在一行,最好分行写

循环语句

Lua支持 while,repeat 和 for循环语句

while 语句的形式为:

while 条件表达式  do 

         语句块

end

repeat语句的形式为:

repeat 语句块 until  条件表达式

for语句有两种形式,一种是数字形式:

for 变量 = 初值 ,终值,步长 do 语句块  end 

其中步长可以省略,默认步长是1,比如使用for循环计算1~100的和

local sum = 0

for i=1 ,100 do sum = sum+1 end

提示: for语句中的循环变量是局部变量,作用域为for循环体内,虽然没有使用local声明,但不是全局变量

for 语句的通用形式为: for  变量1,变量2,....变量n  in 迭代器 do 语句块 end 

表类型

表是Lua中唯一的数据结构,可以理解为关联数组,任何类型的值(除了空类型)都可以作为表的索引

表的定义方式: 

a = {} -- 将变量a赋值为一个空表

a['field'] = 'value'

print(a.field); --打印内容为'value',a.field是a['field']的语法糖

或者定义: 

people = {name = 'zhouy',age = 29 }  print {people.name} --打印内容为Bob

当索引为整数的时候表和传统的数组一样,例如:

a = {} a[1] = 'zhouy'  a[2] = 'Jeff' 可以写成这样: a = { 'zhouy','jeff'} print{a[1]} 

note: Lua 约定数组的索引是从1开始的,而不是0

表的遍历方式:

1. 通用形式的for语句遍历数组

for index,value in ipairs(a) do 

      print(index)

      print(value)

end 

ipairs是lua内置的函数,实现类似迭代器的功能

2.使用数字形式的for语句遍历数组

for i =1 ,#a do 

     print(i)

     print(a[i])

end 

#a作用是获取表a的长度

3. 迭代器pairs用来遍历非数组的表值。

people = {name = 'zhouy',age = 29}

for index, value in pairs(people) do 

    print (index)

    print(value)

end

pairs和ipairs的区别是前者会遍历所有值不为nil的索引,而后者只会从索引1开始递增遍历到最后一个值不为nil的整数索引

函数

函数的定义为: 

function (参数列表) 

    函数体

end

可以将其赋值为一个局部变量,比如

local square = function(num ) return num*num end

如果没有参数,括号也不能省略。Lua还提供了一个语法糖来简化函数的定义,比如

local function square (num) 

        return num*num

end

这段代码会转换为:

local square 

        square = function (num) return num*num

end

如果实参的个数小于形参的个数,则没有品牌到的形参的值为nil.相对应的,如果实参的个数大于形参的个数,则多出来的实参

会被忽略。如果希望捕获多出的实参,可以让最后一个形参为...。比如,希望传入若干个参数计算这些数的平方

local function square (...)

local argn = {...}

for i=1,#argv do 

     argv[i] = argv [i] * argv[i]

end

unpack函数用来返回表中的元素

标准库

String库 

1>获取字符串长度  string.len(string)

2>转换大小写 string.lower  string.upper

3>获取子字符串 string.sub(string,start,end)  索引从1开始,-1代表最后一个元素。end参数如果省略,默认是-1

Table库

1> 将数组转为字符串

table.concat(table[,sep[, i[, j ]  ]  ]  );

举个例子

print (table.concat({1,2,2},',',2);  ---> '1,2,22'

2>向数组中插入元素

table.insert(table,[post,] value)  ;向 指定索引位置pos插入元素value,并将后面的元素顺序后移,默认pos的值是数组长度加1,即在数组尾部插入,注意索引从1开始的

3> 从数组中弹出一个元素

table.remove(table [,pos])  从指定索引位置删除元素,并将后面的元素前移,返回删除元素的值

其他需要了解的:

cjson.encode :序列化为字符串

cjson.decode :将序列化后的字符串还原为表

cmsgpack.unpack 将序列化后的字符串还原为表

 


你可能感兴趣的:(redis,Redis学习笔记)