1. 程式人生 > 其它 >lua 基本語法

lua 基本語法

技術標籤:Linuxluanginx伺服器centos

  • 刪除一個全域性變數,只要將變數值賦值為nil:a = nil,當且僅當一個變數不為nil 時,這個變數存在
  • Boolean型別:在控制條件中除了falsenil為假,其他值都為真,所以lua認為0和空字串也是真
  • String型別:
    • 字串替換:string.gsub()
      a = 'one HELLO'
      b = string.gsub(a,'one','two')
      print(a)    -- one HELLO
      print(b)    -- two HELLO
    • 字串和數字
      print("10" + 1)       -- 11
      print("10" + "1")     -- 11
      print("10 + 1")       -- 10 + 1
      print("hello " .. " world")  -- hello  world
      --print("hello" + 1)  -- 錯誤寫法
    • 字串和數字轉換
      a = 10
      print(tostring(a))  -- 10
      b = "20"
      print(tonumber(b))  -- "20"
      
      print(tostring(10) == "10")  -- true
      print(10 .. "" == "10")      -- true
  • 表示式
    • 如果兩個值型別不相等,Lua認為兩者不同
    • nil 只和自己相等
    • 邏輯運算子
      -- a and b          -- 如果a為false,則返回a ,否則返回b
      -- a or b          --  如果a為true,則返回a ,否則返回b
      print(4 and 5)      -- 5
      print(nil and 12 )  -- nill
      print(false and 12) -- false
      print(4 or 5)       -- 4
      print(false or 5)   -- 5
    • 注意:and的優先順序比or
    • Lua 三元運算子:
    • a=4
    • b=5
    • local a, b, ret
    • ret = a > b and a or b
    • -- a大於b成立就輸出a ,不成立就輸出b
  • 變數
    • 賦值語句
      x = 20
      y = 30
      x,y = y,x
      print(x,y) -- 30 20
      
      a,b,c = 10,20
      print(a,b,c) --10 20 nil
      
      x,y,z = 10
      print(x,y,z) -- 10 nil nil
    • 區域性變數與程式碼塊
      • 程式碼塊:指一個控制結構內,一個函式體,或者一個chunk(變數被宣告的哪個檔案或者文字串)
      • a = 12
        if a>10 then
           local i = 19
            print(i)  -- 19
        end
        print(i)      -- nil
  • 控制語句
    members = { Tom = 10, Jake = 11, Dodo = 12, Jhon = 16 }
    
    for k, v in pairs(members) do
        if v == 10 then
            print(k, 'is 10 years old')     -- Tom	is 10 years old
        elseif v == 11 then
            print(k, 'is 11 years old')     -- Jake	is 11 years old
        elseif v == 12 then
            print(k, 'is 12 years old')     -- Dodo	is 12 years old
        else
            print(k, "is not 10,11,12 years old")   -- Jhon	is not 10,11,12 years old
        end
    end
  • 函式
    • 單個返回值
      function max(a,b)
          if a > b then
              return a
          else
              return b
          end
      end
      print(max(10,20)) -- 20
    • 多個返回值
      function more()
          return 10 , 20 ,30
      end
      a , b , c = more()
      print(a,b,c) -- 10 20 30
    • 可變數目的引數
      function more()
          return 10 , 20 ,30
      end
      -- 當函式位於最後一位的時候,返回全部值,否則值返回一個數值
      a , b , c ,d = 100, more()
      print(a,b,c,d) -- 100 10 20 30
    • 閉合函式
      function count()
          -- i屬於一個非區域性變數,因為它既不是全域性變數,也不是單純的區域性變數(因為另外一個函式可以訪問到它)
          local i = 0
          return function()
              i =i +1
              return i
          end
      end
      -- 以上 count()函式裡的那個函式,加上一個非全域性變數i,就構成一個閉合函式
      -- 所以每次呼叫閉合函式,非區域性變數的值都不會被重置
      local func = count()
      print(func())   -- 1
      print(func())   -- 2
    • 非全域性函式,在定義函式的使用要注意定義函式的順序
      local eat
      local drink
      eat = function()
          print("eat")
          return drink() -- 這裡的drink()屬於尾呼叫
      end
      drink = function()
          print("drink")
      end
      eat()
  • table 使用
    • Lua table 第一個索引為1
    • 簡單
      a = {}
      a.x = 100 --在這裡可以簡單理解為table中的key 
      a.y = 200
      a.sb = 400
      a["z"] = 300 -- a.z = 300
      print(a.x) -- 100
      print(a.y) -- 200
      print(a.sb) -- 400
  • 泛型迭代器
    • 標準庫迭代器包括:
      • 迭代檔案每行:io.lines
      • 迭代table元素:pairs
        • 可以遍歷表中的所有key和value
        • 並且除了迭代器本身以及遍歷表本身,還可以返回nil
      • 迭代陣列元素:ipairs
        • ipairs不能返回nil,只能返回數字0,如果遇到nil則退出
        • 只能遍歷表中出現的第一個不是整數的key
    • 泛型迭代器
      config = {host = '127.0.0.1',port = '3306', dbname = 'LuaDB' }
      config.redis_host = "192.168.1.1"
      config.redis_port = "6379"
      config.redis_db = "12"
      print(config['redis_host'])     -- 192.168.1.1
      print(config.redis_port)        -- 6379
      print(config.dbname)            -- LuaDB
      
      for k, v in pairs(config) do
          print(k,v)
      end
      
      --[[
      host    127.0.0.1
      dbname	LuaDB
      redis_host	192.168.1.1
      redis_db	12
      redis_port	6379
      port	3306
      -- ]]
    • 迭代table元素
      arr = {}
      for var = 1,100 do      -- for 迴圈
          table.insert(arr,1,var) --1是指定索引的位置,可寫不不寫,預設是插值在最後位置
      end
      
      for k, v in pairs(arr) do   -- 遍歷表
          print(k,v)
      end
      --[[ 列印結果
      1	100
      2	99
      ... ...
      99	2
      100	1
      
      -- ]]
      print(table.maxn(arr))  -- table長度 100
      print(#arr)     -- table長度(快捷方式) 100
    • 迭代陣列元素:ipairs
      arr = {host = '127.0.0.1',port = '3306','Tinywan'}
      -- 如果沒有找到下標為整數的則直接退出,是整數的則直接輸出,如上面的'Tinywan'
      for k, v in ipairs(arr) do  -- 只能遍歷key 為整數的下標
          print(k,v)   -- 1   Tinywan
      end
  • -- 這裡區分陣列和table 字典的區別主要看ipairs 函式和pairs 帶i的是遍歷陣列格式的
    • 迴圈迭代table元素(如:lua-resty-mysql 擴充套件查詢的資料)
      • 查詢 :res, err, errcode, sqlstate = db:query("select * from tb_ngx_test order by id asc", 10)
      • 轉換成JSON結果集輸出2條記錄:
            ngx.say("result: ", cjson.encode(res))
            result: [{"age":"24123","name":"tinywan123","address":"China","id":"1"},{"age":"24","name":"tinywan","address":"China","id":"2"}]
      • 遍歷該結果集:
        res, err, errcode, sqlstate = db:query("select * from tb_ngx_test order by id asc", 10)
        if not res then
            ngx.say("bad result: ", err, ": ", errcode, ": ", sqlstate, ".")
            return
        end
        
        for k, v in pairs(res) do
            if type(v) == "table" then
                for new_table_index, new_table_value in pairs(v) do
                    ngx.say(new_table_index.." = "..new_table_value)
                end
            else
                ngx.say(k,v)
            end
        end
        
        --[[ 列印結果
            age = 24123
            name = tinywan123
            address = China
            id = 1
            age = 24
            name = tinywan
            address = China
            id = 2 
        ]]
    • json 和 lua table 轉換
      • [1] 將 json 轉換成 lua table
        local json_str = '{"is_male":"nan","name":"zhangsan","id":1}'
        local t = json.decode(json_str)
        ngx.say(format_table(t))
      • [2] 將 lua table 轉換成 json 字串
        local t = [[{key="table key",value="table value"}]]
        local json_str = json.encode(t)
        ngx.say(json_str) -- "{key=\"table key\",value=\"table value\"}"
      • [3] 將lua table轉換成 json 陣列 (lua 兩個大括號表示一個數組)
        local t = {keys={"list1","list2","list3"},num=1}
        local str = json.encode(t)
        ngx.say(str)  -- {"keys":["list1","list2","list3"],"num":1}
  • 編譯執行與錯誤
    • error 錯誤
      local name = "Lua1"
      if name ~= "Lua"
      then
          error("this is not Lua  ");
      end
    • assert 錯誤:assert(name~="Lua"," this is not Lua")
    • pcall 捕獲錯誤程式碼
      function test()
          print(a[1])
      end
      -- pcall 除了會返回true或者false外,還能返回函式的錯誤資訊。
      -- 如果沒有錯誤資訊,err 會返回一個nil
      local status,err = pcall(test)
      if status then
          print('success')
      else
          print('函式執行出錯了')
          print('錯誤資訊:',err)
      end
  • Lua面向物件(重點)
    • 部落格詳細地址描述
    • :white_check_mark:__add元方法 #demo1
      local mt = {}
      mt.__add = function(t1, t2)
          print("兩個Table 相加的時候會呼叫我")
      end
      local t1 = {}
      local t2 = {}
      -- 給兩個table 設定新的元表,一個元表就是一個table的值
      setmetatable(t1, mt) -- meta:元素
      setmetatable(t2, mt)
      -- 進行相加操作
      local t = t1 + t2
      print(t)
      
      --[[輸出結果
      兩個Table 相加的時候會呼叫我
      nil
      --]]
    • :white_check_mark:__add元方法 #demo2
      -- 建立一個元表 (是建立一個類嗎?)
      local mt = {}
      mt.__add = function(s1, s2)
          local result = ""
          if s1.sex == "boy" and s2.sex == "girl" then
              result = "一個男孩和一個女孩的家庭"
          elseif s1.sex == "girl" and s2.sex == "girl" then
              result = "兩個女孩的家庭"
          else
              result = "未知孩子的家庭"
          end
          return result
      end
      -- 建立兩個table,可以想象成是兩個類的物件(例項化兩個類)
      local s1 = { name = "Per1", sex = "boy" }
      local s2 = { name = "Per2", sex = "girl" }
      -- 給兩個table 設定新的元表,一個元表就是一個table的值
      setmetatable(s1, mt)
      setmetatable(s2, mt)
      -- 進行加法操作
      local result = s1 + s2
      print(result) 
      
      -- 輸出結果 一個男孩和一個女孩的家庭
    • :white_check_mark:__index元方法 #demo1
      local t = {
          name = "Tinywan"
      }
      local mt = {
          __index = function(table, key)
              print("雖然你呼叫了我不存在的欄位和方法,不過沒關係,我能檢測出來" .. key)
          end
      }
      setmetatable(t, mt)
      print(t.name)
      print(t.age)
      
      --[[輸出結果
      -- Tinywan
      -- 雖然你呼叫了我不存在的欄位和方法,不過沒關係,我能檢測出來age
      -- nil
      ---- ]]
    • :white_check_mark:__index元方法 #demo2
      local t = {
          name = "Tinywan"
      }
      local mt = {
          money = 808080
      }
      
      mt.__index = mt
      setmetatable(t, mt)
      print(t.money)
      -- 輸出結果 808080
    • :white_check_mark:__index元方法 #demo3
      local t = {
          name = "Tinywan"
      }
      local mt = {
          __index = {
              money = 909090
          }
      }
      setmetatable(t, mt)
      print(t.money)
      -- 輸出結果 909090
    • :white_check_mark:__index元方法 #demo4
      local smartMan = {
          name = "Tinywan",
          age = 26,
          money = 800000,
          say_fun = function()
              print("Tinywan say 大家好")
          end
      }
      
      local t1 = {}
      local t2 = {}
      local mt = { __index = smartMan } -- __index 可以是一個表,也可以是一個函式
      setmetatable(t1, mt)
      setmetatable(t2, mt)
      print(t1.money)
      t2.say_fun()
      --- 輸出結果
      -- 800000
      -- Tinywan say 大家好
    • Lua面向物件1
    • Lua面向物件1
    • Lua面向物件3 更新中...
  • Lua 排序演算法
    • Lua 排序演算法 - 選擇排序
    • 選擇排序
      local function selectionSort(arr)
          for i = 1,#arr-1 do
              local idx = i
              -- 迭代剩下的元素,尋找最小的元素
              for j = i+1,#arr do
                  if arr[j] < arr[idx] then
                      idx = j
                  end
              end
              -- 
              arr[i],arr[idx]= arr[idx],arr[i]
          end
      end
      
      local list = {
          -81, -93, -36.85, -53, -31, 79, 45.94, 36, 94, -95.03, 11, 56, 23, -39,
          14, 1, -20.1, -21, 91, 31, 91, -23, 36.5, 44, 82, -30, 51, 96, 64, -41
      }
      
      selectionSort(list)
      print(table.concat( list, ", "))

控制結構

Lua 實現簡單封裝

Table 操作常用的方法

  • table.concat (table [, sep [, start [, end]]])
    • concat是concatenate(連鎖, 連線)的縮寫. table.concat()函式列出引數中指定table的陣列部分從start位置到end位置的所有元素, 元素間以指定的分隔符(sep)隔開
    • demo
      fruits = {"banana","orange","apple"}
      -- 返回 table 連線後的字串 value = banana orange apple
      print("連線後的字串 ",table.concat(fruits))
      -- 指定連線字元   value = banana, orange, apple
      print("指定連線字元連線後的字串 ",table.concat(fruits,", "))
  • table.insert (table, [pos,] value):
    • 在table的陣列部分指定位置(pos)插入值為value的一個元素. pos引數可選, 預設為陣列部分末尾
    • demo
      fruits = {"banana","orange","apple"}
      
      -- 在末尾插入
      table.insert(fruits,"Tinywan4")
      print("索引為 4 的元素為 ",fruits[4]) -- 索引為 4 的元素為 	Tinywan
      
      -- 在索引為 2 的鍵處插入
      table.insert(fruits,2,'Tinywan2')
      print("索引為 2 的元素為 ",fruits[2])  -- 索引為 2 的元素為 	Tinywan
      
      print("最後一個元素為 ",fruits[5])     -- 最後一個元素為 	Tinywan4
      table.remove(fruits)
      print("移除後最後一個元素為 ",fruits[5])  -- 移除後最後一個元素為 	nil
  • table.sort (table [, comp])
    • 對給定的table進行升序排序

Lua 模組與包

  • 定義:Lua 的模組是由變數、函式等已知元素組成的 table,因此建立一個模組很簡單,就是建立一個 table,然後把需要匯出的常量、函式放入其中,最後返回這個 table 就行.
  • Table 操作常用的方法
    • table.concat()
    • table.insert()
    • table.maxn()
    • table.concat()
  • Lua 實現簡單封裝
    • man.lua

          local _name = "Tinywan"
          local man = {}
      
          function man.GetName()
              return _name
          end
      
          function man.SetName(name)
              _name = name    
          end
      
          return man 

測試封裝,test.lua

  •     local man = require('man')
        print("The man name is "..man.GetName())
        man.SetName("Phalcon")
        print("The man name is "..man.GetName())