Lua 是一門強大、輕量的嵌入式腳本語言,可供任何須要的程序使用。Lua 沒有 "main" 程序的概念: 它只能 嵌入 一個宿主程序中工做.宿主程序能夠調用函數執行一小段 Lua 代碼,能夠讀寫 Lua 變量,能夠註冊 C 函數讓 Lua 代碼調用。
Lua 是一門動態類型語言。 這意味着變量沒有類型;只有值纔有類型。
Lua 中全部的值都是 一等公民。 這意味着全部的值都可保存在變量中、 看成參數傳遞給其它函數、以及做爲返回值。
文檔:5.3:http://cloudwu.github.io/lua5...
5.1:http://book.luaer.cn/html
Lua 中有八種基本類型: nil、boolean、number、string、function、userdata、 thread 和 table。
Nil 是值 nil 的類型.和Python中None,Java中null相似。
Boolean 是 false 與 true 兩個值的類型。與其餘語言不通的是nil 和 false 都會致使條件判斷爲假; 而其它任何值都表示爲真。
而其它語言判斷好比0時爲假,但lua爲真。
Number 表明了整數和實數(浮點數)。 它也按需做自動轉換
String 表示一個不可變
的字節序列。Lua 的字符串與編碼無關
; 它不關心字符串中具體內容。
Lua 能夠調用(以及操做)用 Lua 或 C 編寫的函數。 這兩種函數有統一類型 function。
userdata 類型容許將 C 中的數據保存在 Lua 變量中。 用戶數據類型的值是一個內存塊, 有兩種用戶數據: 徹底用戶數據 ,指一塊由 Lua 管理的內存對應的對象; 輕量用戶數據 ,則指一個簡單的 C 指針。 用戶數據在 Lua 中除了賦值與相等性判斷以外沒有其餘預約義的操做。 經過使用 元表 ,程序員能夠給徹底用戶數據定義一系列的操做。 你只能經過 C API 而沒法在 Lua 代碼中建立或者修改用戶數據的值, 這保證了數據僅被宿主程序所控制。
thread 類型表示了一個獨立的執行序列,被用於實現協程 。 Lua 的線程與操做系統的線程毫無關係
。 Lua 爲全部的系統,包括那些不支持原生線程的系統,提供了協程支持。
table 是一個關聯數組, 也就是說,這個數組不只僅以數字作索引,除了 nil 和 NaN 以外的全部 Lua 值 均可以作索引。(Not a Number 是一個特殊的數字,它用於表示未定義或表示不了的運算結果,好比 0/0。) 表能夠是 異構 的; 也就是說,表內能夠包含任何類型的值( nil 除外)。
表是 Lua 中惟一的數據結構, 它可被用於表示普通數組、序列、符號表、集合、記錄、圖、樹等等。 對於記錄,Lua 使用域名做爲索引。 語言提供了 a.name 這樣的語法糖來替代 a["name"]。
咱們使用 序列 這個術語來表示一個用 {1..n} 的正整數集作索引的表.注意:lua中索引從1開始,而非0
和索引同樣,表中每一個域的值也能夠是任何類型。 須要特別指出的是:既然函數是一等公民,那麼表的域也能夠是函數。 這樣,表就能夠攜帶 方法 了。python
表、函數、線程、以及徹底用戶數據在 Lua 中被稱爲 對象: 變量並不真的 持有 它們的值,而僅保存了對這些對象的 引用。 賦值、參數傳遞、函數返回,都是針對引用而不是針對值的操做, 這些操做均不會作任何形式的隱式拷貝。nginx
庫函數 type 用於以字符串形式返回給定值的類型。git
因爲 Lua 是一門嵌入式擴展語言,其全部行爲均源於宿主程序中 C 代碼對某個 Lua 庫函數的調用。 (單獨使用 Lua 時,lua 程序就是宿主程序。) 因此,在編譯或運行 Lua 代碼塊的過程當中,不管什麼時候發生錯誤, 控制權都返回給宿主,由宿主負責採起恰當的措施(好比打印錯誤消息)。
能夠在 Lua 代碼中調用 error 函數來顯式地拋出一個錯誤。 若是你須要在 Lua 中捕獲這些錯誤, 能夠使用 pcall 或 xpcall 在 保護模式 下調用一個函數。
不管什麼時候出現錯誤,都會拋出一個攜帶錯誤信息的 錯誤對象 (錯誤消息),這是一個字符串對象。
使用 xpcall 或 lua_pcall 時, 你應該提供一個 消息處理函數 用於錯誤拋出時調用。 該函數需接收原始的錯誤消息,並返回一個新的錯誤消息。程序員
Lua 中的每一個值均可以有一個 元表。 這個 元表 就是一個普通的 Lua 表, 它用於定義原始值在特定操做下的行爲。元表中的鍵對應着不一樣的 事件 名; 鍵關聯的那些值被稱爲 元方法。
你能夠用 getmetatable
函數 來獲取任何值的元表。
使用 setmetatable
來替換一張表的元表。在 Lua 中,你不能夠改變表之外其它類型的值的元表 (除非你使用調試庫); 若想改變這些非表類型的值的元表,請使用 C API。
表和徹底用戶數據有獨立的元表 (固然,多個表和用戶數據能夠共享同一個元表)。 其它類型的值按類型共享元表; 也就是說全部的數字都共享同一個元表, 全部的字符串共享另外一個元表等等。
元表決定了一個對象在數學運算、位運算、比較、鏈接、 取長度、調用、索引時的行爲。 元表還能夠定義一個函數,當表對象或用戶數據對象在垃圾回收時調用它。
其它具體見文檔。。。。github
Lua 採用了自動內存管理。Lua 實現了一個增量標記-掃描收集器。
垃圾收集元方法:
你能夠爲表設定垃圾收集的元方法,對於徹底用戶數據, 則須要使用 C API 。 該元方法被稱爲 終結器。 終結器容許你配合 Lua 的垃圾收集器作一些額外的資源管理工做 (例如關閉文件、網絡或數據庫鏈接,或是釋放一些你本身的內存)。
若是要讓一個對象(表或用戶數據)在收集過程當中進入終結流程, 你必須 標記 它須要觸發終結器。 當你爲一個對象設置元表時,若此刻這張元表中用一個以字符串 "__gc
" 爲索引的域,那麼就標記了這個對象須要觸發終結器。redis
調用函數 coroutine.create
可建立一個協程。 其惟一的參數是該協程的主函數。 create 函數只負責新建一個協程並返回其句柄 (一個 thread 類型的對象); 而不會啓動該協程。數據庫
調用 coroutine.resume
函數執行一個協程。
協程的運行可能被兩種方式終止: 正常途徑是主函數返回 (顯式返回或運行完最後一條指令); 非正常途徑是發生了一個未被捕獲的錯誤。 對於正常結束, coroutine.resume 將返回 true, 並接上協程主函數的返回值。 當錯誤發生時, coroutine.resume 將返回 false 與錯誤消息。數組
經過調用 coroutine.yield
使協程暫停執行,讓出執行權。 協程讓出時,對應的最近 coroutine.resume 函數會馬上返回,即便該讓出操做發生在內嵌函數調用中 (即不在主函數,但在主函數直接或間接調用的函數內部)。 在協程讓出的狀況下, coroutine.resume 也會返回 true, 並加上傳給 coroutine.yield 的參數。 當下次重啓同一個協程時, 協程會接着從讓出點繼續執行。緩存
與 coroutine.create 相似, coroutine.wrap
函數也會建立一個協程。 不一樣之處在於,它不返回協程自己,而是返回一個函數。 調用這個函數將啓動該協程。 傳遞給該函數的任何參數均看成 coroutine.resume 的額外參數。 coroutine.wrap 返回 coroutine.resume 的全部返回值,除了第一個返回值(布爾型的錯誤碼)。 和 coroutine.resume 不一樣, coroutine.wrap 不會捕獲錯誤; 而是將任何錯誤都傳播給調用者。
下面的代碼展現了一個協程工做的範例:
function foo (a) print("foo", a) return coroutine.yield(2*a) end co = coroutine.create(function (a,b) print("co-body", a, b) local r = foo(a+1) print("co-body", r) local r, s = coroutine.yield(a+b, a-b) print("co-body", r, s) return b, "end" end) print("main", coroutine.resume(co, 1, 10)) print("main", coroutine.resume(co, "r")) print("main", coroutine.resume(co, "x", "y")) print("main", coroutine.resume(co, "x", "y")) 當你運行它,將產生下列輸出: co-body 1 10 foo 2 main true 4 co-body r main true 11 -9 co-body x y main true 10 end main false cannot resume dead coroutine
你也能夠經過 C API 來建立及操做協程: 參見函數 lua_newthread, lua_resume, 以及 lua_yield。
Lua 語言的格式自由。 它會忽略語法元素(符記)間的空格(包括換行)和註釋, 僅把它們看做爲名字和關鍵字間的分割符。
Lua 語言對大小寫敏感。
字面串 能夠用單引號或雙引號括起。 字面串內部能夠包含下列 C 風格的轉義串。轉義串 'z'
會忽略其後的一系列空白符,包括換行; 它在你須要對一個很長的字符串常量斷行爲多行並但願在每一個新行保持縮進時很是有用。
對於用 UTF-8 編碼的 Unicode 字符,你能夠用 轉義符 u{XXX} 來表示
代碼註釋:
--這是行註釋 --[[這是塊 註釋]]
Lua 中有三種變量: 全局變量、局部變量和表的域。
全部沒有顯式聲明爲局部變量的變量名都被當作全局變量
。 這一點卻是和js很類似。
全局變量 x = 1234 的賦值等價於 _ENV
.x = 1234
局部變量 local
namelist [‘=’ explist] 好比 local name='xbynet'
每一個語句結尾的分號(;)是可選的,但若是同一行有多個語句最好用;分開
-- file 'lib1.lua' function norm (x, y) local n2 = x^2 + y^2 return math.sqrt(n2) end function twice (x) return 2*x end
在交互模式下:
> lua -i > dofile("lib1.lua") -- load your library > n = norm(3.4, 1.0) > print(twice(n)) --> 7.0880180586677
-i和dofile在調試或者測試Lua代碼時是很方便的。
命令行方式
> lua -e "print(math.sin(12))" --> -0.53657291800043
全局變量arg存放Lua的命令行參數。
prompt> lua script a b c
在運行之前,Lua使用全部參數構造arg
表。腳本名索引爲0,腳本的參數從1開始增長。腳本前面的參數從-1開始減小。
if, while, and repeat 這些控制結構符合一般的意義,並且也有相似的語法:
while exp do block end repeat block until exp if exp then block elseif exp then block else block end
for 有兩種形式:一種是數字形式,另外一種是通用形式。
數值for循環:
for var=exp1,exp2,exp3 do loop-part end
for將用exp3做爲step從exp1(初始值)到exp2(終止值),執行loop-part。其中exp3能夠省略,默認step=1
有幾點須要注意:
三個表達式只會被計算一次,而且是在循環開始前。
for i=1,f(x) do
print(i)
end
for i=10,1,-1 do
print(i)
end
第一個例子f(x)只會在循環前被調用一次。
通用形式的 for 經過一個叫做 迭代器 的函數工做。 每次迭代,迭代器函數都會被調用以產生一個新的值, 當這個值爲 nil 時,循環中止。
for var_1, ···, var_n in explist do block end -- print all values of array 'a' for i,v in ipairs(a) do print(v) end 再看一個遍歷表key的例子: -- print all keys of table 't' for k in pairs(t) do print(k) end
控制結構中的條件表達式能夠返回任何值。 false 與 nil 二者都被認爲是假。 全部不一樣於 nil 與 false 的其它值都被認爲是真 (特別須要注意的是,數字 0 和空字符串也被認爲是真)。
有break,可是沒有continue
return 被用於從函數或是代碼塊(其實它就是一個函數) 中返回值。 函數能夠返回不止一個值。
return 只能被寫在一個語句塊的最後一句。 若是你真的須要從語句塊的中間 return, 你可使用顯式的定義一個內部語句塊, 通常寫做 do return end。 能夠這樣寫是由於如今 return 成了(內部)語句塊的最後一句了。
Lua語法要求break和return只能出如今block的結尾一句
(也就是說:做爲chunk的最後一句,或者在end以前,或者else前,或者until前),例如:
local i = 1 while a[i] do if a[i] == v then break end i = i + 1 end
有時候爲了調試或者其餘目的須要在block的中間使用return或者break,能夠顯式的使用do..end來實現:
function foo () return --<< SYNTAX ERROR -- 'return' is the last statement in the next block do return end -- OK ... -- statements not reached end
數學運算操做符
+: 加法 -: 減法 *: 乘法 /: 浮點除法 //: 向下取整除法 %: 取模 ^: 乘方 -: 取負
比較操做符
==: 等於 ~=: 不等於 <: 小於 >: 大於 <=: 小於等於 >=: 大於等於
注意:不等因而~=,而不是!=
這些操做的結果不是 false 就是 true。
等於操做 (==)先比較操做數的類型。 若是類型不一樣,結果就是 false。 不然,繼續比較值。 字符串按通常的方式比較。 數字遵循二元操做的規則
表,用戶數據,以及線程都按引用比較: 只有二者引用同一個對象時才認爲它們相等。
你能夠經過使用 "eq" 元方法來改變 Lua 比較表和用戶數據時的方式。
邏輯操做符
Lua 中的邏輯操做符有 and, or,以及 not
。
和控制結構同樣, 全部的邏輯操做符把 false 和 nil 都做爲假, 而其它的一切都看成真。
字符串鏈接
Lua 中字符串的鏈接操做符寫做兩個點('..
')。 若是兩個操做數都是字符串或都是數字, 鏈接操做將以中提到的規則把其轉換爲字符串。 不然,會調用元方法 __concat
多行字符串
還可使用[[...]]表示字符串。這種形式的字符串能夠包含多行
page = [[ qwwqwq adas ss ]]
取長度操做符
取長度操做符寫做一元前置符 #
。 字符串的長度是它的字節數(就是以一個字符一個字節計算的字符串長度)。而Python是內置的len()函數,Java和JS都是字符串函數.length()
程序能夠經過 __len 元方法來修改對字符串類型外的任何值的取長度操做行爲。
表構造子是一個構造表的表達式。 每次構造子被執行,都會構造出一張新的表。 構造子能夠被用來構造一張空表, 也能夠用來構造一張表並初始化其中的一些域。
構造器是建立和初始化表的表達式。表是Lua特有的功能強大的東西。最簡單的構造函數是{}
,用來建立一個空表。能夠直接初始化數組:
days = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}
Lua將"Sunday"初始化days[1](第一個元素索引爲1),用"Monday"初始化days[2]...
若是想初始化一個表做爲record使用能夠這樣:
a = {x=0, y=0} <--> a = {}; a.x=0; a.y=0
無論用何種方式建立table,咱們均可以向表中添加或者刪除任何類型的域,構造函數僅僅影響表的初始化。
w = {x=0, y=0, label="console"} x = {sin(0), sin(1), sin(2)} w[1] = "another field" x.f = w print(w["x"]) --> 0 print(w[1]) --> another field print(x.f[1]) --> another field w.x = nil -- remove field "x"
值得注意的是:w.x = nil -- remove field "x"
在構造函數中域分隔符逗號(",")能夠用分號(";")替代,一般咱們使用分號用來分割不一樣類型的表元素。
{x=10, y=45; "one", "two", "three"}
舉個例子:
a = { [f(1)] = g; "x", "y"; x = 1, f(x), [30] = 23; 45 }
等價於
do local t = {} t[f(1)] = g t[1] = "x" -- 1st exp t[2] = "y" -- 2nd exp t.x = 1 -- t["x"] = 1 t[3] = f(x) -- 3rd exp t[30] = 23 t[4] = 45 -- 4th exp a = t end
若是表單中最後一個域的形式是 exp , 並且其表達式是一個函數調用或者是一個可變參數, 那麼這個表達式全部的返回值將依次進入列表
函數定義
function f () body end local function f () body end
當一個函數被調用, 若是函數並不是一個 可變參數函數, 即在形參列表的末尾註明三個點 ('...
'), 那麼實參列表就會被調整到形參列表的長度。
function f(a, b) end function g(a, b, ...) end function r() return 1,2,3 end
下面看看實參到形參數以及可變長參數的映射關係:
CALL PARAMETERS f(3) a=3, b=nil f(3, 4) a=3, b=4 f(3, 4, 5) a=3, b=4 f(r(), 10) a=1, b=10 f(r()) a=1, b=2 g(3) a=3, b=nil, ... --> (nothing) g(3, 4) a=3, b=4, ... --> (nothing) g(3, 4, 5, 8) a=3, b=4, ... --> 5 8 g(5, r()) a=5, b=1, ... --> 2 3
冒號 語法能夠用來定義 方法, 就是說,函數能夠有一個隱式的形參 self。 所以,以下語句
function t.a.b.c:f (params) body end
是這樣一種寫法的語法糖
t.a.b.c.f = function (self, params) body end
Lua函數能夠返回多個結果值
function maximum (a) local mi = 1 -- maximum index local m = a[mi] -- maximum value for i,val in ipairs(a) do if val > m then mi = i m = val end end return m, mi end print(maximum({8,10,23,12,5})) --> 23 3
Lua老是調整函數返回值的個數以適用調用環境,看成爲獨立的語句調用函數時,全部返回值將被忽略
第一,看成爲表達式調用函數時,有如下幾種狀況:
當調用做爲表達式最後一個參數或者僅有一個參數時,根據變量個數函數儘量多地返回多個值,不足補nil,超出捨去。
其餘狀況下,函數調用僅返回第一個值(若是沒有返回值爲nil)
第二,函數調用做爲函數參數被調用時,和多值賦值是相同。
第三,函數調用在表構造函數中初始化時,和多值賦值時相同。
可變參數與命名參數
printResult = "" function print(...) for i,v in ipairs(arg) do printResult = printResult .. tostring(v) .. "\t" end printResult = printResult .. "\n" end
命名參數用表來做爲參數傳遞。
Lua 語言有詞法做用範圍。 變量的做用範圍開始於聲明它們以後的第一個語句段, 結束於包含這個聲明的最內層語句塊的最後一個非空語句。
x = 10 -- 全局變量 do -- 新的語句塊 local x = x -- 新的一個 'x', 它的值如今是 10 print(x) --> 10 x = x+1 do -- 另外一個語句塊 local x = x+1 -- 又一個 'x' print(x) --> 12 end print(x) --> 11 end print(x) --> 10 (取到的是全局的那一個)
局部變量能夠被在它的做用範圍內定義的函數自由使用。 當一個局部變量被內層的函數中使用的時候, 它被內層函數稱做 上值,或是 外部局部變量。
注意,每次執行到一個 local 語句都會定義出一個新的局部變量。 看看這樣一個例子:
a = {} local x = 20 for i=1,10 do local y = 0 a[i] = function () y=y+1; return x+y end end
這個循環建立了十個閉包(這指十個匿名函數的實例)。 這些閉包中的每個都使用了不一樣的 y 變量, 而它們又共享了同一份 x。
因爲,目前關注重點在於簡單的redis與Lua及nginx與lua交互,故而暫時略去此部分學習。。。
全部的庫都是直接用 C API 實現的,並以分離的 C 模塊形式提供。 目前,Lua 有下列標準庫:
基礎庫
協程庫
包管理庫
字符串控制
基礎 UTF-8 支持
表控制
數學函數
輸入輸出
操做系統庫
調試庫
(只列出一些我的認爲對初學者經常使用的)
assert (v [, message])
若是其參數 v 的值爲假(nil 或 false), 它就調用 error; 不然,返回全部的參數。 在錯誤狀況時, message 指那個錯誤對象; 若是不提供這個參數,參數默認爲 "assertion failed!" 。
dofile ([filename])
打開該名字的文件,並執行文件中的 Lua 代碼塊。
error (message [, level])
停止上一次保護函數調用, 將錯誤對象 message 返回。level 參數指明瞭怎樣得到出錯位置。 對於 level 1 (默認值),出錯位置指 error 函數調用的位置。 Level 2 將出錯位置指向調用 error的函數的函數;以此類推。 傳入 level 0 能夠避免在消息前添加出錯位置信息。
_G
一個全局變量(非函數), 內部儲存有全局環境。 Lua 本身不使用這個變量; 改變這個變量的值不會對任何環境形成影響,反之亦然。
_VERSION
一個包含有當前解釋器版本號的全局變量(並不是函數)。 當前這個變量的值爲 "Lua 5.3"。
getmetatable (object)
若是 object 不包含元表,返回 nil 。 不然,若是在該對象的元表中有 "__metatable" 域時返回其關聯值, 沒有時返回該對象的元表。
ipairs (t)
如下代碼for i,v in ipairs(t) do body end
將迭代鍵值對(1,t[1]) ,(2,t[2]), ... ,直到第一個空值。
pairs (t)
for k,v in pairs(t) do body end
能迭表明 t 中的全部鍵值對。
load (chunk [, chunkname [, mode [, env]]])
加載一個代碼塊。
若是 chunk 是一個字符串,代碼塊指這個字符串。 若是 chunk 是一個函數, load 不斷地調用它獲取代碼塊的片段。 每次對 chunk 的調用都必須返回一個字符串牢牢鏈接在上次調用的返回串以後。 當返回空串、nil、或是不返回值時,都表示代碼塊結束。
若是沒有語法錯誤, 則以函數形式返回編譯好的代碼塊; 不然,返回 nil 加上錯誤消息。
若是結果函數有上值, env 被設爲第一個上值。 若不提供此參數,將全局環境替代它。
chunkname 在錯誤消息和調試消息中,用於代碼塊的名字。 若是不提供此參數,它默認爲字符串chunk 。
字符串 mode 用於控制代碼塊是文本仍是二進制(即預編譯代碼塊)。 它能夠是字符串 "b" (只能是二進制代碼塊), "t" (只能是文本代碼塊), 或 "bt" (能夠是二進制也能夠是文本)。 默認值爲 "bt"。
loadfile ([filename [, mode [, env]]])
和 load 相似, 不過是從文件 filename 或標準輸入(若是文件名未提供)中獲取代碼塊。
next (table [, index])
運行程序來遍歷表中的全部域。 第一個參數是要遍歷的表,第二個參數是表中的某個鍵。 next 返回該鍵的下一個鍵及其關聯的值。 特別指出,你能夠用 next(t) 來判斷一張表是不是空的。
pcall (f [, arg1, ···])
傳入參數,以 保護模式 調用函數 f 。 這意味着 f 中的任何錯誤不會拋出; 取而代之的是,pcall 會將錯誤捕獲到,並返回一個狀態碼。 第一個返回值是狀態碼(一個布爾量), 當沒有錯誤時,其爲真。 此時,pcall 一樣會在狀態碼後返回全部調用的結果。 在有錯誤時,pcall 返回 false 加錯誤消息。
xpcall (f, msgh [, arg1, ···])
這個函數和 pcall 相似。 不過它能夠額外設置一個消息處理器 msgh。
print (···)
接收任意數量的參數,並將它們的值打印到 stdout。 它用 tostring
函數將每一個參數都轉換爲字符串。 print 不用於作格式化輸出。完整的對輸出的控制,請使用 string.format
以及 io.write
。
tostring (v)
能夠接收任何類型,它將其轉換爲人可閱讀的字符串形式。
select (index, ···)
若是 index 是個數字, 那麼返回參數中第 index 個以後的部分; 負的數字會從後向前索引(-1 指最後一個參數)。 不然,index 必須是字符串 "#", 此時 select 返回參數的個數。
tonumber (e [, base])
若是調用的時候沒有 base, tonumber 嘗試把參數轉換爲一個數字。
type (v)
類型判斷, 函數可能的返回值有 "nil" (一個字符串,而不是 nil 值), "number", "string", "boolean", "table", "function", "thread", "userdata"。
關於協程的操做做爲基礎庫的一個子庫, 被放在一個獨立表 coroutine 中。
coroutine.create (f)
建立一個主體函數爲 f 的新協程。 f 必須是一個 Lua 的函數。 返回這個新協程,它是一個類型爲 "thread" 的對象。
coroutine.isyieldable ()
若是正在運行的協程可讓出,則返回真。
不在主線程中或不在一個沒法讓出的 C 函數中時,當前協程是可以讓出的。
coroutine.resume (co [, val1, ···])
開始或繼續協程 co 的運行。 當你第一次延續一個協程,它會從主體函數處開始運行。 val1, ... 這些值會以參數形式傳入主體函數。 若是該協程被讓出,resume 會從新啓動它; val1, ... 這些參數會做爲讓出點的返回值。
若是協程運行起來沒有錯誤, resume 返回 true 加上傳給 yield 的全部值 (當協程讓出), 或是主體函數的全部返回值(當協程停止)。 若是有任何錯誤發生, resume 返回 false 加錯誤消息。
coroutine.running ()
返回當前正在運行的協程加一個布爾量。 若是當前運行的協程是主線程,其爲真。
coroutine.status (co)
以字符串形式返回協程 co 的狀態: 當協程正在運行(它就是調用 status 的那個) ,返回 "running"; 若是協程調用 yield 掛起或是尚未開始運行,返回 "suspended"; 若是協程是活動的,都並不在運行(即它正在延續其它協程),返回 "normal"; 若是協程運行完主體函數或因錯誤中止,返回 "dead"。
coroutine.wrap (f)
建立一個主體函數爲 f 的新協程。 f 必須是一個 Lua 的函數。 返回一個函數, 每次調用該函數都會延續該協程。 傳給這個函數的參數都會做爲 resume 的額外參數。 和 resume 返回相同的值, 只是沒有第一個布爾量。 若是發生任何錯誤,拋出這個錯誤。
coroutine.yield (···)
掛起正在調用的協程的執行。 傳遞給 yield 的參數都會轉爲 resume 的額外返回值。
包管理庫提供了從 Lua 中加載模塊的基礎庫。 只有一個導出函數直接放在全局環境中: require
。 全部其它的部分都導出在表 package
中。
require (modname)
加載一個模塊。 這個函數首先查找 package.loaded
表, 檢測 modname 是否被加載過。 若是被加載過,require 返回 package.loaded[modname] 中保存的值。 不然,它試着爲模塊尋找 加載器 。(require 遵循 package.searchers 序列的指引來查找加載器。)
package.path
這個路徑被 require 在 Lua 加載器中作搜索時用到。
在啓動時,Lua 用環境變量 LUA_PATH_5_3 或環境變量 LUA_PATH
來初始化這個變量。
package.searchers
用於 require 控制如何加載模塊的表。
package.searchpath (name, path [, sep [, rep]])
在指定 path 中搜索指定的 name 。
其他,請看文檔。
這個庫提供了字符串處理的通用函數。 例如字符串查找、子串、模式匹配等。 當在 Lua 中對字符串作索引時,第一個字符從 1 開始計算(而不是 C 裏的 0 )。 索引能夠是負數,它指從字符串末尾反向解析。 即,最後一個字符在 -1 位置處,等等。
字符串庫中的全部函數都在表 string 中。字符串庫假定採用單字節字符編碼。(這意味着不是原生支持中文。)
string.byte (s [, i [, j]])
返回字符 s[i], s[i+1], ... ,s[j] 的內部數字編碼。
string.char (···)
接收零或更多的整數。 返回和參數數量相同長度的字符串。
string.find (s, pattern [, init [, plain]])
查找第一個字符串 s 中匹配到的 pattern 。 若是找到一個匹配,find 會返回 s 中關於它起始及終點位置的索引; 不然,返回 nil。 第三個可選數字參數 init 指明從哪裏開始搜索; 默認值爲 1 ,同時能夠是負值。 第四個可選參數 plain 爲 true 時, 關閉模式匹配機制。 此時函數僅作直接的 「查找子串」的操做.
string.format (formatstring, ···)
返回不定數量參數的格式化版本, 格式化串爲第一個參數(必須是一個字符串)。 格式化字符串遵循 ISO C 函數 sprintf 的規則。
string.match (s, pattern [, init])
在字符串 s 中找到第一個能用 pattern (參見 §6.4.1)匹配到的部分。 若是能找到,match 返回其中的捕獲物; 不然返回 nil 。 若是 pattern 中未指定捕獲, 返回整個 pattern 捕獲到的串。 第三個可選數字參數 init 指明從哪裏開始搜索; 它默認爲 1 且能夠是負數。
string.gmatch (s, pattern)
返回一個迭代器函數。 每次調用這個函數都會繼續以 pattern (參見 §6.4.1) 對 s 作匹配,並返回全部捕獲到的值。 若是 pattern 中沒有指定捕獲,則每次捕獲整個 pattern。
下面這個例子會循環迭代字符串 s 中全部的單詞, 並逐行打印:
s = "hello world from Lua" for w in string.gmatch(s, "%a+") do print(w) end
下一個例子從指定的字符串中收集全部的鍵值對 key=value 置入一張表:
t = {} s = "from=world, to=Lua" for k, v in string.gmatch(s, "(%w+)=(%w+)") do t[k] = v end
對這個函數來講,模板前開始的 '^' 不會當成錨點。由於這樣會阻止迭代。
string.sub (s, i [, j])
返回 s 的子串, 該子串從 i 開始到 j 爲止; i 和 j 均可覺得負數。
string.gsub (s, pattern, repl [, n])
將字符串 s 中,全部的(或是在 n 給出時的前 n 個) pattern (參見 §6.4.1)都替換成 repl ,並返回其副本。 repl 能夠是字符串、表、或函數。 gsub 還會在第二個返回值返回一共發生了多少次匹配。 這個和python中的re.sub有點相似。
若是 repl 是一個字符串,那麼把這個字符串做爲替換品。 字符 % 是一個轉義符: repl 中的全部形式爲 %d 的串表示 第 d 個捕獲到的子串,d 能夠是 1 到 9 。 串 %0 表示整個匹配。 串 %% 表示單個 %。
若是 repl 是張表,每次匹配時都會用第一個捕獲物做爲鍵去查這張表。
若是 repl 是個函數,則在每次匹配發生時都會調用這個函數。 全部捕獲到的子串依次做爲參數傳入。
這裏有一些用例:
x = string.gsub("hello world", "(%w+)", "%1 %1") --> x="hello hello world world" x = string.gsub("hello world", "%w+", "%0 %0", 1) --> x="hello hello world" x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1") --> x="world hello Lua from" x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv) --> x="home = /home/roberto, user = roberto" x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s) return load(s)() end) --> x="4+5 = 9" local t = {name="lua", version="5.3"} x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t) --> x="lua-5.3.tar.gz"
string.len (s)
接收一個字符串,返回其長度。 空串 "" 的長度爲 0 。
string.lower (s)
接收一個字符串,將其中的大寫字符都轉爲小寫後返回其副本。
string.upper (s)
string.pack (fmt, v1, v2, ···)
string.unpack (fmt, s [, pos])
返回一個打包了(即以二進制形式序列化) v1, v2 等值的二進制字符串。 字符串 fmt 爲打包格式
string.rep (s, n [, sep])
返回 n 個字符串 s 以字符串 sep 爲分割符連在一塊兒的字符串。 默認的 sep 值爲空字符串(即沒有分割符)。
string.reverse (s)
返回字符串 s 的翻轉串。
Lua 中的匹配模式直接用常規的字符串來描述。 它用於模式匹配函數 string.find, string.gmatch, string.gsub, string.match
。
字符類:
字符類 用於表示一個字符集合。 下列組合可用於字符類:
x: (這裏 x 不能是 魔法字符 ^$()%.[]*+-? 中的一員) 表示字符 x 自身。
.: (一個點)可表示任何字符。
%a: 表示任何字母。
%c: 表示任何控制字符。
%d: 表示任何數字。
%g: 表示任何除空白符外的可打印字符。
%l: 表示全部小寫字母。
%p: 表示全部標點符號。
%s: 表示全部空白字符。
%u: 表示全部大寫字母。
%w: 表示全部字母及數字。
%x: 表示全部 16 進制數字符號。
%x: (這裏的 x 是任意非字母或數字的字符) 表示字符 x。 這是對魔法字符轉義的標準方法。 全部非字母或數字的字符 (包括全部標點,也包括非魔法字符) 均可以用前置一個 '%' 放在模式串中表示自身。
交叉使用類和範圍的行爲未定義。 所以,像 [%a-z] 或 [a-%%] 這樣的模式串沒有意義。
全部單個字母表示的類別(%a,%c,等), 若將其字母改成大寫,均表示對應的補集。 例如,%S 表示全部非空格的字符。
如何定義字母、空格、或是其餘字符組取決於當前的區域設置。 特別注意:[a-z] 未必等價於 %l 。
模式條目:
模式條目 能夠是
單個字符類匹配該類別中任意單個字符;
單個字符類跟一個 '*', 將匹配零或多個該類的字符。 這個條目老是匹配儘量長的串;
單個字符類跟一個 '+', 將匹配一或更多個該類的字符。 這個條目老是匹配儘量長的串;
單個字符類跟一個 '-', 將匹配零或更多個該類的字符。 和 '*' 不一樣, 這個條目老是匹配儘量短的串;
單個字符類跟一個 '?', 將匹配零或一個該類的字符。 只要有可能,它會匹配一個;
%n, 這裏的 n 能夠從 1 到 9; 這個條目匹配一個等於 n 號捕獲物(後面有描述)的子串。
%bxy, 這裏的 x 和 y 是兩個明確的字符; 這個條目匹配以 x 開始 y 結束, 且其中 x 和 y 保持 平衡 的字符串。 意思是,若是從左到右讀這個字符串,對每次讀到一個 x 就 +1 ,讀到一個 y 就 -1, 最終結束處的那個 y 是第一個記數到 0 的 y。 舉個例子,條目 %b() 能夠匹配到括號平衡的表達式。
%f[set], 指 邊境模式; 這個條目會匹配到一個位於 set 內某個字符以前的一個空串, 且這個位置的前一個字符不屬於 set 。 集合 set 的含義如前面所述。 匹配出的那個空串之開始和結束點的計算就當作該處有個字符 '0' 同樣。
模式:
模式 指一個模式條目的序列。 在模式最前面加上符號 '^' 將錨定從字符串的開始處作匹配。 在模式最後面加上符號 '$' 將使匹配過程錨定到字符串的結尾。 若是 '^' 和 '$' 出如今其它位置,它們均沒有特殊含義,只表示自身。
捕獲:
模式能夠在內部用小括號括起一個子模式; 這些子模式被稱爲 捕獲物。 當匹配成功時,由 捕獲物 匹配到的字符串中的子串被保存起來用於將來的用途。 捕獲物以它們左括號的次序來編號。 例如,對於模式 "(a(.)%w(%s))" , 字符串中匹配到 "a(.)%w(%s)" 的部分保存在第一個捕獲物中 (所以是編號 1 ); 由 "." 匹配到的字符是 2 號捕獲物, 匹配到 "%s*" 的那部分是 3 號。
做爲一個特例,空的捕獲 () 將捕獲到當前字符串的位置(它是一個數字)。 例如,若是將模式 "()aa()" 做用到字符串 "flaaap" 上,將產生兩個捕獲物: 3 和 5 。
這個庫提供了對 UTF-8 編碼的基礎支持。 全部的函數都放在表 utf8 中。
utf8.char (···)
接收零或多個整數, 將每一個整數轉換成對應的 UTF-8 字節序列,並返回這些序列鏈接到一塊兒的字符串。
utf8.charpattern
用於精確匹配到一個 UTF-8 字節序列的模式(是一個字符串,並不是函數)"0-x7FxC2-xF4*"
utf8.len (s [, i [, j]])
返回字符串 s 中 從位置 i 到 j 間 (包括兩端) UTF-8 字符的個數。 默認的 i 爲 1 ,默認的 j 爲 -1 。
utf8.offset (s, n [, i])
返回編碼在 s 中的第 n 個字符的開始位置(按字節數) (從位置 i 處開始統計)。
其他看文檔
這個庫提供了表處理的通用函數。 全部函數都放在表 table 中。
table.concat (list [, sep [, i [, j]]])
返回字符串 list[i]..sep..list[i+1] ··· sep..list[j]。 sep 的默認值是空串, i 的默認值是 1 , j 的默認值是 #list 。 若是 i 比 j 大,返回空串。
table.insert (list, [pos,] value)
在 list 的位置 pos 處插入元素 value , 並後移元素 list[pos], list[pos+1], ···, list[#list] 。 pos 的默認值爲 #list+1 , 所以調用 table.insert(t,x) 會將 x 插在列表 t 的末尾。
table.remove (list [, pos])
移除 list 中 pos 位置上的元素,並返回這個被移除的值。
table.sort (list [, comp])
在表內從 list[1] 到 list[#list] 原地 對其間元素按指定次序排序。 若是提供了 comp , 它必須是一個能夠接收兩個列表內元素爲參數的函數。 當第一個元素須要排在第二個元素以前時,返回真 (所以 not comp(list[i+1],list[i]) 在排序結束後將爲真)。
table.pack (···)
返回用全部參數以鍵 1,2, 等填充的新表, 並將 "n" 這個域設爲參數的總數。 注意這張返回的表不必定是一個序列。
table.unpack (list [, i [, j]])
返回列表中的元素。 這個函數等價於
return list[i], list[i+1], ···, list[j]
i 默認爲 1 ,j 默認爲 #list。
這個庫提供了基本的數學函數。 因此函數都放在表 math 中。
略。。。
I/O 庫提供了兩套不一樣風格的文件處理接口。 第一種風格使用隱式的文件句柄; 它提供設置默認輸入文件及默認輸出文件的操做, 全部的輸入輸出操做都針對這些默認文件。 第二種風格使用顯式的文件句柄。
當使用隱式文件句柄時, 全部的操做都由表 io 提供。 若使用顯式文件句柄, io.open
會返回一個文件句柄,且全部的操做都由該文件句柄的方法來提供。
表 io 中也提供了三個 和 C 中含義相同的預約義文件句柄: io.stdin, io.stdout, 以及 io.stderr
。 I/O 庫永遠不會關閉這些文件。
I/O 函數在出錯時都返回 nil (第二個返回值爲錯誤消息,第三個返回值爲系統相關的錯誤碼)。 成功時返回與 nil 不一樣的值。
隱式文件句柄操做
io.close ([file])
等價於 file:close()。 不給出 file 時將關閉默認輸出文件。
io.flush ()
io.lines ([filename ···])
以讀模式打開指定的文件名並返回一個迭代函數。 此迭代函數的工做方式和用一個已打開的文件去調用 file:lines(···) 獲得的迭代器相同。 當迭代函數檢測到文件結束, 它不返回值(讓循環結束)並自動關閉文件。
調用 io.lines() (不傳文件名) 等價於 io.input():lines("*l"); 即,它將按行迭代標準輸入文件。 在此狀況下,循環結束後它不會關閉文件。
io.open (filename [, mode])
這個函數用字符串 mode 指定的模式打開一個文件。 返回新的文件句柄。 當出錯時,返回 nil 加錯誤消息。
mode 字符串能夠是下列任意值:
"r": 讀模式(默認);
"w": 寫模式;
"a": 追加模式;
"r+": 更新模式,全部以前的數據都保留;
"w+": 更新模式,全部以前的數據都刪除;
"a+": 追加更新模式,全部以前的數據都保留,只容許在文件尾部作寫入。
mode 字符串能夠在最後加一個 'b' , 這會在某些系統上以二進制方式打開文件。
io.popen (prog [, mode])
這個函數和系統有關,不是全部的平臺都提供。
用一個分離進程開啓程序 prog, 返回的文件句柄可用於從這個程序中讀取數據 (若是 mode 爲 "r",這是默認值) 或是向這個程序寫入輸入(當 mode 爲 "w" 時)。
io.input ([file])
用文件名調用它時,(以文本模式)來打開該名字的文件, 並將文件句柄設爲默認輸入文件。 若是用文件句柄去調用它, 就簡單的將該句柄設爲默認輸入文件。 若是調用時不傳參數,它返回當前的默認輸入文件。
io.read (···)
等價於 io.input():read(···)。
io.tmpfile ()
返回一個臨時文件的句柄。 這個文件以更新模式打開,在程序結束時會自動刪除。
io.type (obj)
檢查 obj 是不是合法的文件句柄。 若是 obj 它是一個打開的文件句柄,返回字符串 "file"。 若是 obj 是一個關閉的文件句柄,返回字符串 "closed file"。 若是 obj 不是文件句柄,返回 nil 。
io.output ([file])
相似於 io.input。 不過都針對默認輸出文件操做。
io.write (···)
等價於 io.output():write(···)。
顯式文件句柄操做
若使用顯式文件句柄, io.open
會返回一個文件句柄
file:close ()
關閉 file。
file:flush ()
將寫入的數據保存到 file 中。
file:lines (···)
返回一個迭代器函數, 每次調用迭代器時,都從文件中按指定格式讀數據。 若是沒有指定格式,使用默認值 "l" 。 看一個例子
for c in file:lines(1) do body end
會從文件當前位置開始,中不斷讀出字符。 和 io.lines 不一樣, 這個函數在循環結束後不會關閉文件。
file:read (···)
讀文件 file, 指定的格式決定了要讀什麼。 對於每種格式,函數返回讀出的字符對應的字符串或數字。 若不能以該格式對應讀出數據則返回 nil。 (對於最後這種狀況, 函數不會讀出後續的格式。) 當調用時不傳格式,它會使用默認格式讀下一行(見下面描述)。
提供的格式有
"n": 讀取一個數字,根據 Lua 的轉換文法,可能返回浮點數或整數。 (數字能夠有前置或後置的空格,以及符號。) 只要能構成合法的數字,這個格式老是去讀儘可能長的串; 若是讀出來的前綴沒法構成合法的數字 (好比空串,"0x" 或 "3.4e-"), 就停止函數運行,返回 nil。
"i": 讀取一個整數,返回整數值。
"a": 從當前位置開始讀取整個文件。 若是已在文件末尾,返回空串。
"l": 讀取一行並忽略行結束標記。 當在文件末尾時,返回 nil 這是默認格式。
"L": 讀取一行並保留行結束標記(若是有的話), 當在文件末尾時,返回 nil。
number: 讀取一個不超過這個數量字節數的字符串。 當在文件末尾時,返回 nil。 若是 number 爲零, 它什麼也不讀,返回一個空串。 當在文件末尾時,返回 nil。
格式 "l" 和 "L" 只能用於文本文件。
file:seek ([whence [, offset]])
設置及獲取基於文件開頭處計算出的位置。 設置的位置由 offset 和 whence 字符串 whence 指定的基點決定。基點能夠是:
"set": 基點爲 0 (文件開頭);
"cur": 基點爲當前位置了;
"end": 基點爲文件尾;
當 seek 成功時,返回最終從文件開頭計算起的文件的位置。 當 seek 失敗時,返回 nil 加上一個錯誤描述字符串。
whence 的默認值是 "cur", offset 默認爲 0 。 所以,調用 file:seek() 能夠返回文件當前位置,並不改變它; 調用 file:seek("set") 將位置設爲文件開頭(並返回 0); 調用 file:seek("end") 將位置設到文件末尾,並返回文件大小。
file:setvbuf (mode [, size])
設置輸出文件的緩衝模式。 有三種模式:
"no": 不緩衝;輸出操做馬上生效。
"full": 徹底緩衝;只有在緩存滿或當你顯式的對文件調用 flush(參見 io.flush) 時才真正作輸出操做。
"line": 行緩衝; 輸出將到每次換行前, 對於某些特殊文件(例如終端設備)緩衝到任何輸入前。
對於後兩種狀況,size 以字節數爲單位 指定緩衝區大小。 默認會有一個恰當的大小。
file:write (···)
將參數的值逐個寫入 file。 參數必須是字符串或數字。
成功時,函數返回 file。 不然返回 nil 加錯誤描述字符串。
這個庫都經過表 os 實現。
os.clock ()
返回程序使用的按秒計 CPU 時間的近似值。
os.date ([format [, time]])
返回一個包含日期及時刻的字符串或表。 格式化方法取決於所給字符串 format。
若是提供了 time 參數, 格式化這個時間 (這個值的含義參見 os.time 函數)。 不然,date 格式化當前時間。
若是 format 以 '!' 打頭, 日期以協調世界時格式化。 在這個可選字符項以後, 如果 format 爲字符串 "*t", date 返回有後續域的表: year (四位數字),month (1–12),day (1–31), hour (0–23),min (0–59),sec (0–61), wday (星期幾,星期天爲 1 ), yday (當年的第幾天), 以及 isdst (夏令時標記,一個布爾量)。 對於最後一個域,若是該信息不提供的話就不存在。
若是 format 並不是 "*t", date 以字符串形式返回, 格式化方法遵循 ISO C 函數 strftime 的規則。
os.difftime (t2, t1)
返回以秒計算的時刻 t1 到 t2 的差值。 (這裏的時刻是由 os.time 返回的值)。
os.execute ([command])
它調用系統解釋器執行 command。 若是命令成功運行完畢,第一個返回值就是 true, 不然是 nil。 在第一個返回值以後,函數返回一個字符串加一個數字。以下:
"exit": 命令正常結束; 接下來的數字是命令的退出狀態碼。
"signal": 命令被信號打斷; 接下來的數字是打斷該命令的信號。
os.exit ([code [, close]])
調用 ISO C 函數 exit 終止宿主程序。 若是 code 爲 true, 返回的狀態碼是 EXIT_SUCCESS; 若是 code 爲 false, 返回的狀態碼是 EXIT_FAILURE; 若是 code 是一個數字, 返回的狀態碼就是這個數字。 code 的默認值爲 true。
os.getenv (varname)
返回進程環境變量 varname 的值, 若是該變量未定義,返回 nil 。
os.remove (filename)
刪除指定名字的文件(在 POSIX 系統上能夠是一個空目錄) 若是函數失敗,返回 nil 加一個錯誤描述串及出錯碼。
os.rename (oldname, newname)
將名字爲 oldname 的文件或目錄改名爲 newname。 若是函數失敗,返回 nil 加一個錯誤描述串及出錯碼。
os.time ([table])
當不傳參數時,返回當前時刻。 若是傳入一張表,就返回由這張表表示的時刻。 這張表必須包含域 year,month,及 day; 能夠包含有 hour (默認爲 12 ), min (默認爲 0), sec (默認爲 0),以及 isdst (默認爲 nil)。
這個庫裏的全部函數都提供在表 debug
內。 全部操做線程的函數,可選的第一個參數都是針對的線程。 默認值永遠是當前線程。
debug.traceback ([thread,] [message [, level]])
若是 message 有,且不是字符串或 nil, 函數不作任何處理直接返回 message。 不然,它返回調用棧的棧回溯信息。 字符串可選項 message 被添加在棧回溯信息的開頭。 數字可選項 level 指明從棧的哪一層開始回溯 (默認爲 1 ,即調用 traceback 的那裏)。
其餘,請看文檔
雖然 Lua 被設計成一門擴展式語言,用於嵌入一個宿主程序。 但常常也會被當成獨立語言使用。 獨立版的 Lua 語言解釋器隨標準包發佈,就叫 lua。 其命令行用法爲:
lua [options] [script [args]]
選項有:
-e stat: 執行一段字符串 stat ; -l mod: 「請求模塊」 mod ; -i: 在運行完 腳本 後進入交互模式; -v: 打印版本信息; -E: 忽略環境變量; --: 停止對後面選項的處理; -: 把 stdin 看成一個文件運行,並停止對後面選項的處理。
在處理完選項後,lua 運行指定的 腳本。 若是不帶參數調用, 在標準輸入(stdin)是終端時,lua 的行爲和 lua -v -i 相同。 不然至關於 lua - 。
爲了讓 Lua 能夠用於 Unix 系統的腳本解釋器。
若是 lua 在你的 PATH 中, 寫成 #!/usr/bin/env lua更爲通用。
該版本主要實現了對整數、位操做、UTF-8 的支持以及打包和解包的功能。
Lua 5.2 到 Lua 5.3 最大的變化是引入了數字的整數子類型,你能夠經過把數字都強制轉換爲浮點數來消除差別 (在 Lua 5.2 中,全部的數字都是浮點數)。
bit32 庫廢棄了。 使用一個外部兼容庫很容易, 不過最好直接用對應的位操做符來替換它。 (注意 bit32 只能針對 32 位整數運算, 而標準 Lua 中的位操做能夠用於 64 位整數。)
io.read 的選項名再也不用 '*' 打頭。 但出於兼容性考慮,Lua 會繼續忽略掉這個字符。
數學庫中的這些函數廢棄了: atan2, cosh, sinh, tanh, pow, frexp, 以及 ldexp 。 你能夠用 x^y 替換 math.pow(x,y);
require 在搜索 C 加載器時處理版本號的方式有所變化。 如今,版本號應該跟在模塊名後(其它大多數工具都是這樣乾的)。 出於兼容性考慮,若是使用新格式找不到加載器的話,搜索器依然會嘗試舊格式。
能夠參考:http://blog.codingnow.com/201...
http://blog.csdn.net/weiyuefe...
5.1 與 5.2 是徹底不兼容的,相關的第三方庫必須從新爲 5.2 適配。
luajit不支持5.2,5.3
具體見
http://www.lua.org/manual/5.2...