redis學習(八) Lua語法

z1340954953發表於2018-03-08

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



3>邏輯操作符

Lua邏輯操作符
操作符說明
not根據運算元的真和假相應地返回false和true
anda 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 將序列化後的字串還原為表

 


相關文章