Lua腳本之語法基礎快速入門

    Lua的語法基礎超級簡單,很是易於上手,下面總結一些學習過程當中的Lua語法基礎:html

       在開始學習以前,先介紹一些最基本的概念,在Lua中具備一個代碼塊的概念,每一個函數或者for循環等都是一個代碼塊。在Lua中,用 「- - 」來標記該行的註釋,使用「- - [ [」 和   「 - - ] ] 」之間括起來的部分進行塊註釋。以下所示:程序員

[plain] view plaincopyweb

  1. -- 行註釋,僅僅註釋當前行  數組

  2. for idx = 1, 10 do  --在代碼以後進行行註釋  網絡

  3.      print("idx=",idx);    dom

  4. end  函數

  5. --[[  學習

  6. 塊註釋,上邊的for循環結構跟end結合起來就是一個Lua中常見的代碼塊結構。  編碼

  7. --]]  lua

         另外,Lua中支持的算術運算符有:+、-、*、/,即加、減、乘、除;支持的關係運算符有:==、~=(不等於)、<、>、<=、>=;支持的邏輯運算符有:and、or、not。須要注意的是,在Lua中,and邏輯運算符若是第一個參數是false,則返回false,不會執行第二個參數的代碼(即便第二個參數是一個錯誤的表達式,也能順利運行);若是第一個參數是true,返回第二個參數的值。 同理,or邏輯運算符若是第一個參數不是false,則返回第一個參數的值(不會執行第二個參數的代碼);不然返回第二個參數的值。這就是所謂的邏輯運算符短路求值

[plain] view plaincopy

  1. result = true  

  2. if result and an_donot_defined_method() then  

  3.   print("no erro occured!")  

  4. end  

  5. --[[  

  6. 上述代碼輸出的錯誤以下:  

  7. stdin:1: attempt to call global 'an_donot_defined_method' (a nil value)  

  8. stack traceback:  

  9.     stdin:1: in main chunk  

  10.     [C]: ?  

  11. --]]  

  12. result =false   

  13. if (result and an_donot_defined_method())==false  then  

  14.   print("no erro occured!")  

  15. end  

  16. --上述代碼順利經過編譯,即便有一個沒定義的方法,打印結果:no erro occured!  



1、基本數據類型

          Lua中具備5種基本的數據類型,nil、Boolean、string、Number和table在Lua中使用變量不須要提早聲明,變量的類型決定於用戶賦值的類型可使用 type()函數判斷變量的類型。其中,nil、Boolean、Number都是用法比較簡單的類型,string、table類型用法稍微複雜點。給一個變量賦值爲nil,表示釋放該變量。Boolean跟其餘語言同樣,只有true和false兩種值。Number是雙精度浮點數,Lua中沒有整數類型。table類型能夠看成數組使用。

         在Lua中,變量默認是全局的,這一般致使一些調試困難,最好儘可能顯式的在變量名以前加上 local 關鍵字聲明該變量爲局部變量。

[plain] view plaincopy

  1. gNumber = 10  --這是一個默認全局的變量  

  2. print(type(gNumber))  

  3. --輸出結果爲number  

  4. gNumber = nil --以前的number類型gNumber = 10變量被釋放  

  5. print(type(gNumber))  

  6. --輸出結果爲nil  

  7.   

  8. function LocalVarFunction ()  

  9.   local pTable = {} --用local關鍵字聲明一個局部變量,這個變量將在執行LocalVarFunction方法後銷燬  

  10.      for idx = 1, 5 do   

  11.            local result = true  --這個result將在每一個for循環執行以後銷燬  

  12.            if result then   

  13.               local pString = "這個字符串將在if代碼塊以後銷燬"  

  14.               pTable[idx] = pString  

  15.               print(pTable[idx])  

  16.            end  

  17.      end  

  18. end  


      下面詳細介紹string以及table兩種類型的詳細用法。

一、string類型的用法

       Lua中的字符串操做很是出色。下表是一些特殊意義的字符:

特殊的Lua字符串
 字符 意義 字符 意義
     \a 響鈴     \v  垂直製表符 
    \b 退格     \\ 反斜槓
    \f 換頁符     \「 雙引號
    \n 換行符     \' 單引號
    \r 換行符    \[ 左方括號
   \t 製表符    \] 右方括號

     a、類型轉換

     Lua會根據上下文在合理合法的狀況下隱式進行數字和字符之間的轉換。另外,也可使用tonumber()函數和tostring()函數顯式地進行字符與數字的轉換。 見代碼實例:

[plain] view plaincopy

  1. --字符與數字的隱式轉換  

  2. print("10" + 7)  

  3. --輸出結果爲:17,將字符10隱私轉化爲Number類型計算  

  4. print("hello" + 7)  

  5. --沒法進行運算,即不能隱式將"hello"字符轉化爲Number計算  

  6. --[[  

  7.    系統錯誤以下:  

  8. stdin:1: attempt to perform arithmetic on a string value    

  9. stack traceback:    

  10.     stdin:1: in main chunk    

  11.     [C]: ?    

  12. --]]  

  13.   

  14.   

  15.   

  16. --字符與數字的顯式轉換  

  17. print(tonumber("100")+11)  

  18. --輸出結果爲:111  

  19. print(type(tostring(100)))  

  20. --輸出結果爲:string  

      b、經常使用的字符處理函數介紹    string.char()函數根據傳入的ASCII編碼返回該編碼對應的字符。如:string.char(10),表示字符換行符,10是換行符的ASCII編碼。    

    string.len()函數求字符串的長度。如:

[plain] view plaincopy

  1. print(string.len("hello"))  

  2. --輸出結果爲:5  

   string.sub(aString, start, end) 函數返回指定字符串的子串。如:

[plain] view plaincopy

  1. gString = "hello Lua"  

  2. print(string.sub(gString, 7,9))  

  3. --輸出結果爲:Lua  

    string.format()函數格式化輸出指定字符串。%s表示字符串,%d表示全部數字,%D表示非數字,%a表示字母,%c表示控制字符,%l小寫字母,%p標點符號,%s空格符號,%u大寫字母,%w字母數字,%x十六進制數,%z用0表示的字符。加%前綴可讓特殊符號也能用在格式化中(如:().%+_*?[ ^ $ ]),如%%表明百分比符號。%.4f表示小數點後有4位的浮點數,%02d.表示至少有兩個數字的整數,若是不足兩個數字則用0補足。如:

[plain] view plaincopy

  1. aString = "哈哈,你是"  

  2. bString = "一頭豬"  

  3. print(string.format("%s%s", aString, bString))  

  4. --輸出結果爲:哈哈,你是一頭豬  

     sting.find(sourceString, targetString) 函數在sourceString字符串中查找第一個符合targetString字符串的位置,若是找到則返回開始和結束的位置,沒找到則返回nil。

     string.gsub(sourceString, pattern, replacementString) 函數返回一個字符串,sourceString字符中知足pattern格式的字符都會被替換成replacementString參數的值。

     string.gfind(sourceString, pattern) 函數遍歷一個字符串,一旦查找到符合指定格式的字符串就返回該子串。

二、table類型的用法

     通常table能夠當作數組使用,能夠經過table[n]的索引形式訪問任意數組中的某個成員。在Lua中,table還能被當作字典dictionary數據使用,而且數組跟字典的用法還能混合使用(實質上仍是數組,只不過索引從數字變成其餘屬性值)。

     a、使用其餘值做爲table的索引以及多維table

      table還可使用其餘的值做爲索引值,而且能用數字跟其餘值同時做爲同一個table的索引。如:

[plain] view plaincopy

  1. gTable = {}  

  2. gTable.name = "eric"  

  3. gTable.gender = "man"  

  4. gTable.phonenumber = "0000000000"  

  5. gTable[1] = "公司"  

  6. gTable[2] = "部門"  

  7. for index, value in pairs(gTable) do   

  8.   print(index, value)  

  9. end  

  10. --[[  

  11. 輸出結果以下:  

  12. 1   公司  

  13. 2   部門  

  14. phonenumber 0000000000  

  15. gender  man  

  16. name    eric  

  17. --]]  

      注意,上述循環中的pairs()函數能夠遍歷table中的每一對值(索引以及索引對應的value,有點相似字典,不是嗎?)

      事實上,table的索引還能夠是table自己,這樣就組成了一個多維table或多維字典。跟其餘語言的多維數組或字典比起來,使用真是超級方便,很是很是的靈活。如:

[plain] view plaincopy

  1. gTable = {}  

  2. gTable.name = "eric"  

  3. gTable.gender = "man"  

  4. gTable.phonenumber = "0000000000"  

  5. gTable[1] = "公司"  

  6. gTable[2] = "部門"  

  7. gTable.hobby = {"跑步", "讀書", "遊戲", "動漫"}  -- 多維table,能夠經過gTable.hobby[1]的方式訪問.即gTable.hobby自己也是一個table  

  8. gTable.secTable = {}  

  9. gTable.secTable.job = "程序員"  

  10. gTable.secTable.label = "寫代碼的"  

  11. gTable.secTable.description = "職責是實現產品的邏輯"  

  12.   

  13. for index, value in pairs(gTable) do   

  14.   print(index, value)  

  15.   if ("table" == type(value)) then  

  16.      for idx, var in pairs(value) do   

  17.          print("二維table:", idx, var)  

  18.      end  

  19.    end  

  20. end  

  21. --[[  

  22. 輸出結果以下:  

  23. 1   公司  

  24. 2   部門  

  25. hobby   table: 0x7fdceac14bc0  

  26. 二維table:    1   跑步  

  27. 二維table:    2   讀書  

  28. 二維table:    3   遊戲  

  29. 二維table:    4   動漫  

  30. phonenumber 0000000000  

  31. gender  man  

  32. secTable    table: 0x7fdceac15100  

  33. 二維table:    label   寫代碼的  

  34. 二維table:    description 職責是實現產品的邏輯  

  35. 二維table:    job 程序員  

  36. name    eric  

  37. --]]  


     b、table 的經常使用函數

      table.getn()函數,返回table中元素的個數。如:

[plain] view plaincopy

  1. gStringTable = {"a", "b","c","d","e"}  

  2. for i = 1, table.getn(gStringTable) do  

  3.      print(gStringTable[i])  

  4. end  

     table.sort()函數,將table中的元素從小到大排列。如:

[plain] view plaincopy

  1. gNumberTable = {10, 5, 7, 2,3, 2}  

  2. table.sort(gNumberTable)  

  3. for i = 1, table.getn(gNumberTable) do   

  4.    print(gNumberTable[i])  

  5. end  

  6. --輸出結果以下:  

  7. 2  

  8. 2  

  9. 3  

  10. 5  

  11. 7  

  12. 10  

    table.insert(pTable, position, value) 函數在table中插入一個新值,位置參數若是沒指定,則默認將新值插入到table的末尾。

    table.remove(pTable, position) 函數從指定table中刪除指定位置的元素並返回該元素,若是沒有指定刪除的位置,則默認刪除table的最後一個元素。

    

   介紹到這裏, Lua中基本的數據類型諸位應該都能掌握,休息一下,下面接着開始簡單介紹Lua的基本語句以及函數。

2、Lua中的經常使用語句結構以及函數

 一、Lua中的經常使用語句結構介紹

[plain] view plaincopy

  1. --if 語句結構,以下實例:  

  2. gTable = {"hello", 10}  

  3. if nil ~= gTable[1] and "hello" == gTable[1] then  

  4.   print("gTable[1] is" , gStringTable[1])  

  5. elseif  10 == gTable[2] then  

  6.   print("gTable[2] is", gTable[2])  

  7. else   

  8.   print("unkown gTable element")  

  9. end  


[plain] view plaincopy

  1. --while 和repeat循環語句結構,while先判斷條件,若是true才執行代碼塊(有可能跳過該代碼塊);repeat則是在最後判斷條件,保證代碼塊至少執行一次。  

  2. gTable = {1,2,3,4,5,6,7,8,9,10}  

  3. index = 1  

  4. while gTable[index] < 10 do   

  5.    print("while gTable[",index,"] is ",gTable[index])  

  6.    index = index + 1 -- 注意,Lua不支持index++或者index += 1形式的運算符。  

  7. end  

  8. --[[  

  9. while循環輸出結果以下:  

  10. while gTable[   1   ] is    1  

  11. while gTable[   2   ] is    2  

  12. while gTable[   3   ] is    3  

  13. while gTable[   4   ] is    4  

  14. while gTable[   5   ] is    5  

  15. while gTable[   6   ] is    6  

  16. while gTable[   7   ] is    7  

  17. while gTable[   8   ] is    8  

  18. while gTable[   9   ] is    9  

  19. --]]  

  20.   

  21. --上一個循環結束後,index = 10  

  22. repeat  

  23.     print("repeat gTable[",index,"] is ",gTable[index])  

  24.    index = index - 2  

  25. until index < 1  

  26. --[[  

  27. 輸出結果以下:  

  28. repeat gTable[  10  ] is    10  

  29. repeat gTable[  8   ] is    8  

  30. repeat gTable[  6   ] is    6  

  31. repeat gTable[  4   ] is    4  

  32. repeat gTable[  2   ] is    2  

  33. --]]  


[plain] view plaincopy

  1. --for循環結構,for循環結構具備三個參數,初始值,結束值,每一個循環增長值。  

  2. for index = 1, 5 do --不設置第三個參數的話,默認缺省第三個參數是1,即每一個循環 index 增長1  

  3.    print("for cycle index =",index)  

  4. end  

  5. --[[  

  6. 輸出結果爲:  

  7. for cycle index =   1  

  8. for cycle index =   2  

  9. for cycle index =   3  

  10. for cycle index =   4  

  11. for cycle index =   5  

  12. --]]  

  13.   

  14. for index = 20 , 0, -5 do --設定第三個參數爲-5  

  15.  print("for cycle index:",index)  

  16. end  

  17. --[[  

  18. 輸出結果:  

  19. for cycle index:    20  

  20. for cycle index:    15  

  21. for cycle index:    10  

  22. for cycle index:    5  

  23. for cycle index:    0  

  24. --]]  


[plain] view plaincopy

  1. --break關鍵字可使循環強制退出,Lua中沒有continue關鍵字,須要經過其餘方式實現continue關鍵字,好比if-else語句。或者經過網絡下載Lua的continue關鍵字補丁安裝來解決該問題  

  2.   

  3. for index = 1, 100, 5 do   

  4.   if index > 10 and index < 25 then  --用if-else語句實現continue關鍵字的功能  

  5.      print("continue!!!!! index=",index)  

  6.   else   

  7.     if index > 15 and index < 35 then   

  8.        print("break~~~~~index=",index)  

  9.        break  

  10.     end  

  11.     print("At end index=",index)  

  12.   end  

  13. end  

  14.   

  15. --[[  

  16. 輸出結果以下:  

  17. At end index=   1  

  18. At end index=   6  

  19. continue!!!!! index=    11  

  20. continue!!!!! index=    16  

  21. continue!!!!! index=    21  

  22. break~~~~~index=    26  

  23. --]]  


[plain] view plaincopy

  1. --最後還要提的一點是,Lua中switch語句的缺失,用if-elseif-else語句代替的話,顯得很是臃腫,還有其餘的一些實現方案。筆者在網上麥子加菲童鞋的博客中找到一種Lua中代替switch語句很是優雅的方案。下面貼出麥子加菲原代碼:  

  2. --Switch語句的替代語法(全部替代方案中以爲最好,最簡潔,最高效,最能體現Lua特色的一種方案)  

  3. action = {    

  4.   [1] = function (x) print(x) end,    

  5.   [2] = function (x) print( 2 * x ) end,    

  6.   ["nop"] = function (x) print(math.random()) end,    

  7.   ["my name"] = function (x) print("fred") end,    

  8. }    

  9.    

  10. while true do    

  11.     key = getChar()    

  12.     x = math.ramdon()    

  13.     action[key](x)    

  14. end   


二、Lua中的函數

     在Lua腳本中,函數是以function關鍵字開始,而後是函數名稱,參數列表,最後以end關鍵字表示函數結束。須要注意的是,函數中的參數是局部變量,若是參數列表中存在(...)時,Lua內部將建立一個類型爲table的局部變量arg,用來保存全部調用時傳遞的參數以及參數的個數(arg.n)

[plain] view plaincopy

  1. function PrintTable (pTable)  

  2.   for index = 1, table.getn(pTable) do   

  3.       print("pTable[",index,"] =",pTable[index])  

  4.   end  

  5. end  

  6.   

  7. gStringTable = {"hello","how","are","you"}  

  8. PrintTable(gStringTable)  

  9. --[[  

  10. 輸出結果爲:  

  11. pTable[ 1   ] = hello  

  12. pTable[ 2   ] = how  

  13. pTable[ 3   ] = are  

  14. pTable[ 4   ] = you  

  15. --]]  

  16.   

  17. function PrintFriendInfo (name, gender, ...)   

  18.   local friendInfoString = string.format("name:%s  gender:%d",name,gender)  

  19.   if 0 < arg.n then  

  20.      for index = 1, arg.n do   

  21.         friendInfoString = string.format("%s otherInfo:%s",friendInfoString, arg[index])  

  22.      end  

  23.    end  

  24.    print(friendInfoString)  

  25. end  

  26.   

  27.   

  28. PrintFriendInfo ("eric", 1, "程序員","2b", 50)  

  29.   

  30.  --輸出結果爲:  

  31. -- name:eric  gender:1 otherInfo:程序員 otherInfo:2b otherInfo:50  


      Lua函數的返回值跟其餘語言比較的話,特殊的是可以返回多個返回值。return以後,該Lua函數從Lua的堆棧裏被清理

[plain] view plaincopy

  1. function GetUserInfo ()  

  2.     local name = "eric"  

  3.     local gender = 1  

  4.     local hobby = "動漫"  

  5.   return name, gender, hobby  

  6. end  

  7.   

  8. print(GetUserInfo())  

  9.   

  10. --輸出結果:eric 1   動漫  



3、Lua中的庫函數

          在本文的最後,介紹一些Lua中經常使用的庫函數。

          1.數學庫

          math庫的經常使用函數:三角函數math.sin、math.cos、取整函數math.floor、math.ceil、math.max、math.min、隨機函數math.random、math.randomseed(os.time())、變量pi和huge。

          二、I/O庫

         進行I/O操做前,必須先用io.open()函數打開一個文件。io.open()函數存在兩個參數,一個是要打開的文件名,另外一個是模式字符,相似"r"表示讀取、「w」表示寫入並同時刪除文件原來內容,「a」表示追加,「b」表示打開二進制文件。該函數會返回一個表示文件的返回值,若是打開出錯則返回nil,寫入以前須要判斷是否出錯,好比:local file = assert(io.open(filename, 「w」))..使用完畢後,調用io.close(file).或file:close()。

       幾個經常使用I/O函數:io.input ()、io.output ()、 io.read()、 io.write()

[plain] view plaincopy

  1. local file = assert(io.open(filename, 「w」))  

  2. if file ~= nil then  

  3.   file:write("hello lua!!!!")  --注意,等同於io.write("hello lua!!!!")  

  4.   file:close()  --等同於io.close(file)  

  5. end  


         三、調試庫

         debug.getinfo()函數,他的第一個參數 能夠是一個函數或一個棧層。返回結果是一個table,其中包含了函數的定義位置、行號、函數類型、函數名稱等信息。

         debug.getlocal()函數檢查函數任意局部變量,有兩個參數,第一個是但願查詢的函數棧層,另外一個是變量的索引。

         assert(trunk)() 函數,執行參數中代碼塊並在出錯時提供報錯功能

[plain] view plaincopy

  1. a = "hello world"  

  2. b = "print(a)"  

  3. assert(loadstring(b))()  

  4. --輸出結果:  

  5. hello world  

        4、幾個處理Lua碼塊的函數

        loadstring(pString)()函數能夠直接執行pString字符串組成的Lua碼,但不提供報錯功能

[plain] view plaincopy

  1. loadstring("for index = 1, 4 do print(\"for cycle index =\",index) end")()  

  2. --[[  

  3. 輸出結果  

  4. for cycle index =   1  

  5. for cycle index =   2  

  6. for cycle index =   3  

  7. for cycle index =   4  

  8. --]]  


      dofile(filename)函數的功能是載入並馬上執行Lua腳本文件。能夠用來載入定義函數的文件或者數據文件、或當即執行的Lua碼。dofile函數會將程序的執行目錄做爲當前目錄。若是要載入程序執行目錄的子目錄裏的文件,須要加上子目錄的路徑。

[plain] view plaincopy

  1. dofile("/Users/ericli/WorkSpace/Lua語言/hellolua.lua")  

  2. --輸出結果:Hello Lua!  

        本篇總結完畢,本篇只是總結了Lua的一些最基本的語法。至於Lua的更高級的內容,好比:協同程序、模塊與包、Lua調用C碼、C++Lua的整合等,還須要在之後的學習過程當中深刻。


參考資料:

解決Lua語法缺失及替代措施

書籍:《Lua程序設計》、《Lua戲開發實踐指南》

相關文章
相關標籤/搜索