Lua官网
Lua官方文档
Lua5.4参考指南
Lua5.3参考手册(中文版)
Lua菜鸟教程
Lua在线编辑器


Lua基本语法
Lua数据类型
Lua变量
Lua流程控制
Lua函数
Lua运算符
Lua字符串
Lua数组
Lua迭代器
Lua table(表)
Lua模块与包
Lua元表(Metatable)
Lua协同程序(coroutine)
Lua文件I/O
Lua错误处理
Lua调试(Debug)
Lua垃圾回收
Lua面向对象


一、变量类型

--未赋值的变量为nil
--声明字符串变量(单引号或双引号皆可)
--声明number
s = 'my age is: '
i = 16
b = true
print(s, i, b)

--字符串也可以这样写[[字符串内容]]
s = [[s1: hello world!]]
print(s1)

--声明table变量(相当于字典),没key的value用索引访问(索引从1开始)
tab = {web = "www.baidu.com", QQ = 123456, b = true, "no-key-value"}
print("table: ", tab["web"], tab["QQ"], tab["b"], tab[1])

s = "25"
i = 26
--字符串转数字,数字转字符串
print(tonumber(s), tostring(i))


--创建一个函数
function fun(name)
	print("my name is "..name);
end

fun("tom")

运行结果
>lua -e "io.stdout:setvbuf 'no'" "test.lua"
my age is:  16 true
s: hello world!
table:   www.baidu.com  123456 true no-key-value
25 26
my name is tom
>Exit code: 0

局部变量 local

示例1

x = 5
for i = 1, 10000 do
	local x = i
end
print(x)


输出 5

========================================================================================

for循环

--数字for循环
for i = 0, 10, 2 do
	print(i)
end

--泛型for循环,ipairs()是数组的迭代器
arr = {"a", "b", "c", "d"}
for i, v in ipairs(arr) do
	print("arr["..i.."]="..v)
end

 

运行结果

>lua -e "io.stdout:setvbuf 'no'" "test.lua"
0
2
4
6
8
10
arr[1]=a
arr[2]=b
arr[3]=c
arr[4]=d
>Exit code: 0

 

while循环

do
	local i = 1
	local n = 10
	while (i < n) do
		print(i)
		i = i + 1
	end
end

 

repeat循环

i = 1
repeat
i = i + 1
--当until(真)时跳出循环
until(i > 10)

========================================================================================

数学运算操作符
支持:加、减、乘、除、取模、幂

a = 5
b = 6
c = 7
d = 8
--支持: 加、减、乘、除、取模、幂
r = (a + b) * (a - b) / c % 8 + a^(-0.5)
print("r="..r)

========================================================================================

可见性规则(闭包)

a = {}
local x = 20
--创建10个函数闭包
--这些闭包中的每一个都使用了不同的y变量,而它们又共享了同一份x
for i=1,10 do
	local y = 0
	a[i] = function () y=y+1; return x+y end
end
for i=1,10 do
	print(a[i]())
end


输出

21
21
21
21
21
21
21
21
21
21

==========================================================================================

实现继承
__index、setmetatable()

--示例1: 继承
local Car = {}
Car.__index = Car;
function Car:run()
	print("Car:run()")
end

local SuvCar = {}
--SuvCar继承Car
setmetatable(SuvCar, Car)
print(SuvCar.run())

--示例2: 继承
local Car1 = {}
function Car1:new(o)
	o = o or {}
	--o继承Car1
	setmetatable(o, { __index = Car1 })
	return o;
end

function Car1:run()
	print("Car1:run()")
end

--SuvCar1继承Car1
local SuvCar1 = Car1.new()
function SuvCar1:run1()
	print("SuvCar1:run1()")
end

print(SuvCar1.run())
print(SuvCar1.run1())
输出 
Car:run() 
Car1:run()
SuvCar1:run1()

========================================================================================

协程

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))
 --[[
上句输出
co-body 1       10
foo     2
main    true    4
 --]]

--resume方法的参数作为yield()的返回
--yield方法的参数作为resume方法的返回
print("main", coroutine.resume(co, "r"))
 --[[
上句输出
co-body r
main    true    11      -9
 --]]
 
print("main", coroutine.resume(co, "x", "y"))
 --[[
上句输出
co-body x       y
main    true    10      end
 --]]
 
print("main", coroutine.resume(co, "x", "y"))
--[[
上句输出
main    false   cannot resume dead coroutine
--]]
输出:
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


========================================================================================

错误处理

print("--------test pcall------")
function test()
  print("hello world")
  error("wrong value")
end
--pcall,以保护模式调用函数,出错时不打印堆栈信息
print( pcall(test) )

print("--------test xpcall------")
function errhander(e)
  print("error info: "  .. e)
  print("stack info: " .. debug.traceback("current 2 stack: " ,2))
end
function ef()
  error("wrong value")
end
--xpcall,以保护模式调用函数,出错时调用回调方法并打印堆栈信息
print( xpcall(ef,errhander) )


输出: --------test pcall------
hello world
false D:\test.lua:4: wrong value
--------test xpcall------
error info: D:\test.lua:15: wrong value
stack info: current 2 stack:
stack traceback:
[C]: in function 'error'
D:\test.lua:15: in function 'ef'
[C]: in function 'xpcall'
D:\test.lua:18: in main chunk
[C]: in ?
false nil

========================================================================================

环境/全局变量: _ENV

--_ENV是一个普通的全局table,所有的全局变量都会放到_ENV中
--print(type(_ENV))
--定义一个全局变量
my_gobal_var = 123
--访问全局变量
print(my_gobal_var)
print(_ENV.my_gobal_var)
print(_ENV["my_gobal_var"])

--打印所有全局变量
for n in pairs(_ENV) do print(n) end

--判断是否定义了my_gobal_var变量
if my_gobal_var ~= nil then
	print("exits my_gobal_var") --这里会被执行到
end

--覆盖默认环境
_ENV = {print=print}
if my_gobal_var == nil then
	print("not exits my_gobal_var") --这里会被执行到
end

输出:
123
123
123
setmetatable
os
assert
utf8
rawequal
rawset
dofile
loadfile
rawget
require
collectgarbage
my_gobal_var
io
table
pcall
math
package
coroutine
tostring
select
pairs
ipairs
rawlen
next
error
arg
type
print
tonumber
debug
xpcall
string
load
_G
getmetatable
_VERSION
bit32
exits my_gobal_var
not exits my_gobal_var
========================================================================================

table.maxn()
返回table中最大正数索引

t = {t1="a", t2="b", "c", "d", "e", "f", t3="g", "h"}
--连接table中的索引元素
--concat(table, 分隔符, 起始位置, 结束位置)
tab = table.concat(t, "-", 2, 3);
print(tab) --输出 d-e
print(_VERSION)
if _VERSION == "Lua 5.3" then
	print("lua version is 5.3")
	--lua5.3已经移除了maxn函数,需要自己实现
	--函数功能: 返回tabel中最大的正数索引
	table.maxn = function(tab)
		local n = 0
		for k,v in pairs(tab) do
			if type(k) == "number" and k > n then
				n = k
			end
		end
		return n
	end
end

local n = table.maxn(t)
table.insert(t, n+1, "i")

for k,v in pairs(t) do print(k,v) end
print("maxn="..table.maxn(t))

输出:
d-e
Lua 5.3
lua version is 5.3
1       c
2       d
3       e
4       f
5       h
6       i
t3      g
t1      a
t2      b
maxn=6
========================================================================================

table.remove()
删除指定位置的元素

t = {t1="a", t2="b", "c", "d", "e", "f", t3="g", nil, "h", "i", nil}
print("maxn="..#t)
--删除索引为1的元素,后面的元素会自动往前移
table.remove(t, 1)
--删除索引最大的元素
table.remove(t, #t)
--删除t2
t.t2 = nil
for k,v in pairs(t) do print(k,v) end
--安全删除所有以数字索引为key的元素,必须从后往前删
--只会删除找到的第一段连续索引元素
for i = #t, 1, -1 do
	table.remove(t, i)
end
print("deleted all index element")
for k,v in pairs(t) do print(k,v) end

输出
maxn=7
1       d
2       e
5       h
6       i
t1      a
t3      g
deleted all index element
5       h
6       i
t1      a
t3      g

========================================================================================

table.pack()、table.unpack()

t = table.pack(1,"a",2,3) --打包
print("#t="..#t)
print("t.n="..t.n)
for k,v in pairs(t) do print(k,v) end
print("----unpack----")
local a,b,c,d = table.unpack(t) --解包
print(a,b,c,d)
print(table.unpack(t, 2))
print(table.unpack(t, 2, 3))

输出
#t=4
t.n=4
1       1
2       a
3       2
4       3
n       4
----unpack----
1       a       2       3
a       2       3
a       2

========================================================================================

table.move()、table.sort()

t1 = {1, 2, 3, k1="abc"}
t2 = {4, 5, 6, k2="def", 7}
--将t1中的全部索引元素复制到t2中
table.move(t1, 1, #t1, #t2+1, t2)
for k, v in pairs(t2) do print(k, v) end

--注意: 比较函数实际上是重载了<号,所以当>=时都要返回false才行
table.sort(t2, function(a, b)
	--if(a < b) then	return true end --升序
	if(a > b) then	return true end --降序
	return false
	end
)
print("--------sort-------")
for k, v in pairs(t2) do print(k, v) end

输出
1       4
2       5
3       6
4       7
5       1
6       2
7       3
k2      def
--------sort-------
1       7
2       6
3       5
4       4
5       3
6       2
7       1
k2      def
========================================================================================

utf8

os.execute("chcp 936") --cmd中设置代码页为GBK
--os.execute("chcp 65001") --cmd中设置代码页为UTF-8
--每个中文字符占3个字节, Unicode码写法"\u{4E2D}\u{6587}"
local input = "中文Engish" --等效于local input = "\u{4E2D}\u{6587}Engish"
print("len="..utf8.len(input))

print("---------utf8.codes-------")
--遍历字符串中的所有字符
for p, c in utf8.codes(input) do
	print(p, c, utf8.char(c))--打印出字符中Unicode码
end

print("---------utf8.codepoint----")
--获取并打印前两个中文字符(总共占6字节)
print(utf8.codepoint(input, 1, 6))

print("---------utf8.offset----")
--返回第2个字符的开始位置(按字节数),从第1个位置开始统计
print(utf8.offset(input, 2, 1))

print("---------utf8.charpattern----")
--打印所有匹配的UTF-8字符
for c in string.gmatch(input, utf8.charpattern) do
    print(c)
end

输出
活动代码页: 936
len=8
---------utf8.codes-------
1       20013   涓
4       25991   鏂
7       69      E
8       110     n
9       103     g
10      105     i
11      115     s
12      104     h
---------utf8.codepoint----
20013   25991
---------utf8.offset----
4
---------utf8.charpattern----


E
n
g
i
s
h
========================================================================================

string

local s = "Helo,World"
local s1 = "from=world, to=lua"
--打印每个字符的ANSI码
print("byte:", string.byte(s, 1, -1))
--ANSI码转字符串
print("char:", string.char(string.byte(s, 1, -1)))
--搜索第一个匹配的标点符号,第四个参数为true会关闭模式匹配
print("find:", string.find(s, "%p", 1, false))
--格式化字符串
print("format:", string.format('%s,%g,%i', "input-string", 0.5, 1))
--搜寻所有匹配的子串
for k, v in string.gmatch(s1, "(%w+)=(%w+)") do
	print("gmatch:", k, v)
end
--查找并替换
local repl = {name="lua", version="5.3"}
print("gsub", string.gsub("$name-$version.tar.gz", "%$(%w+)", repl)) --替换全部匹配项
print("gsub", string.gsub("$name-$version.tar.gz", "%$(%w+)", repl, 1)) --替换第1个匹配项
print("gsub", string.gsub(s, "(%w+),(%w+)", "%2,%1"))--%1~%9代表匹配到的子项,%0代表这里的s
local s = string.gsub(s, "^%s*(.-)%s*$", "%1") --去除s左右空白字符
--查找匹配
print("match:", string.match(s, "%w+"), 1)--返回第一个匹配串及开始位置
--字符串长度
print("len", string.len(s))
--转成小写
print(string.lower(s))
--转成大写
print(string.upper(s))
--以小端方式打包参数
local fmt = "<I4I4s4f" --格式化参数详见文档
local p = string.pack(fmt, 100, 200, "hello", 0.1)
print("packsize:", string.packsize(p))--输出字节数
print("unpack:", string.unpack(fmt, p, 1)) --解包
--用指定分割符连接字符串
print("rep:", string.rep("ss", 5, "-"))
--反转字符串
print("reverse:", string.reverse(s))
--返回子串
print("sub:", string.sub(s, 1, 5))
--序列化与反序列化函数
function fun()
	print("string.dump test")
end
--将函数序列化为二进制,false代表包含调试信息
local b = string.dump(fun, false)
--对函数反序列化
local f = load(b)
f()

输出
byte:   72      101     108     111     44      87      111     114     108
100
char:   Helo,World
find:   5       5
format: input-string,0.5,1
gmatch: from    world
gmatch: to      lua
gsub    lua-5.3.tar.gz  2
gsub    lua-$version.tar.gz     1
gsub    World,Helo      1
match:  Helo    1
len     10
helo,world
HELO,WORLD
packsize:       8
unpack: 100     200     hello   0.10000000149012        22
rep:    ss-ss-ss-ss-ss
reverse:        dlroW,oleH
sub:    Helo,
string.dump test
========================================================================================

__pairs

local t = {1, 2, nil, 3}
print("------ipairs------")
--ipairs遇到nil就会停止迭代
for k, v in ipairs(t) do
	print("ipairs:", k, v)
end

print("------pairs------")
--pairs会跳过nil继续迭代
for k, v in pairs(t) do
	print("pairs:", k, v)
end

--自定义表的迭代函数
local pairsfunc = function(tbl, key)
	local nk, nv = next(tbl, key) --返回下一对k-v
	if nk then 
		nv = tbl[nk]
	end
	return nk, tostring(nv)..'p' --对返回的值做点改变
end

local mt = {}
mt.__pairs = function(tbl, key)
	return pairsfunc, tbl, nil
end
setmetatable(t, mt) --给t设置元表

print("------__pairs------")
--会调用t的元表中的__pairs函数
for k, v in pairs(t) do
	print("pairs:", k, v)
end

输出
------ipairs------
ipairs: 1       1
ipairs: 2       2
------pairs------
pairs:  1       1
pairs:  2       2
pairs:  4       3
------__pairs------
pairs:  1       1p
pairs:  2       2p
pairs:  4       3p
========================================================================================

rawequal()、rawget()、rawlen()、select()

local t = {1, 2, nil, 3}
local t1 = t
local s = "hello,world"
local s1 = "hello,world"
print("rawequal:", rawequal(t, t1)) --表比较引用
print("rawequal:", rawequal(s, s1)) --字符串比较值
print("rawget:", rawget(t, 1)) --获取元素
print("rawlen:", rawlen(t), rawlen(s)) --获取长度
rawset(t, "k", "v") --设值
local params_count = select("#", 1, 2, 3, 4, 5, "p") --返回参数个数
print("select:", params_count)
local param = select(6, 1, 2, 3, 4, 5, "p") --返回第6个参数
print("select:", param)

输出
rawequal:       true
rawequal:       true
rawget: 1
rawlen: 4       11
select: 6
select: p
========================================================================================

collectgarbage()

print("isrunning:", collectgarbage("isrunning"))
print("stop:", collectgarbage("stop"))
print("isrunning:", collectgarbage("isrunning"))
print("restart:", collectgarbage("restart"))
print("isrunning:", collectgarbage("isrunning"))
print("count:", tostring(collectgarbage("count")).."kb")
print("step:", collectgarbage("step", 10))
print("step:", collectgarbage("step", 10))
--获取lua占用的内存数(单位kb)
print("count:", tostring(collectgarbage("count")).."kb")
--设置步进倍率为内存分配的2倍速度
print("setstepmul:", collectgarbage("setstepmul", 200))
--设置间歇率,当总使用内存达到之前的2倍时开始新的一轮收集
print("setpause:", collectgarbage("setpause", 200))
--做一次完整的垃圾收集循环,collect是默认选项
print("collect:", collectgarbage("collect"))
--步长设置大点希望一步就执行完收集工作
print("step:", collectgarbage("step", 60))

输出
isrunning:      true
stop:   0
isrunning:      false
restart:        0
isrunning:      true
count:  25.9775390625kb
step:   false
step:   true
count:  24.50390625kb
setstepmul:     200
setpause:       200
collect:        0
step:   true
========================================================================================

函数

--定义全局函数
function gfun()

end

--定义局部函数
local function locfun()

end

local Foo = {}
Foo.name = "Job"
--定义局部函数
function Foo.fun(...)
	local tbl = {...} --以参数为内容创建一张表
	print(tbl[1])
	local p1 = select(1, ...) --获取第1个参数
	print("Foo.fun:", p1, ...)
	return ...
end
--定义局部函数
Foo.fun1 = function(...)
	print("fun1")
end
--定义局部函数,self参数是个隐藏参数,会自动传入
function Foo:fun2(x, y)
	print("fun2:", "x="..tostring(x), "y="..tostring(y), "name="..self.name)
end
--定义局部函数
function Foo.fun3(self, x, y)
	print("fun3:", "x="..tostring(x), "y="..tostring(y), "name="..self.name)
end
print("Foo.fun: return ", Foo.fun(1, 2, 3))
--把函数调用括起来只接收返回的第一个值
print("(Foo.fun): return ", (Foo.fun(1, 2, 3)))

--函数写在前面只会返回一个值
local a, b, c, d = Foo.fun(1,2,3), 4
print("return1:", a, b, c, d)
--函数会返回所有值
local a, b, c, d = 4, Foo.fun(1,2,3)
print("return2:", a, b, c, d)

--调用冒号定义的函数
Foo.fun2(Foo, 10, 20) --必须显示传入self
Foo:fun2(10, 20) --会自动隐式传入self
--调用点号定义的函数
Foo.fun3(Foo, 10, 20) --必须显示传入self

输出
1
Foo.fun:        1       1       2       3
Foo.fun: return         1       2       3
1
Foo.fun:        1       1       2       3
(Foo.fun): return       1
1
Foo.fun:        1       1       2       3
return1:        1       4       nil     nil
1
Foo.fun:        1       1       2       3
return2:        4       1       2       3
fun2:   x=10    y=20    name=Job
fun2:   x=10    y=20    name=Job
fun3:   x=10    y=20    name=Job
========================================================================================

UpValue

function fun1()
	local a = 1 --外层变量就是内嵌函数的UpValue
	local fun2 = function()
		a = a + 1
		return a
	end
	return fun2
end
--内嵌函数脱离外层函数时依然可以访问UpValue
local f1 = fun1()
print("f1:", f1())
print("f1:", f1())
--
local f2 = fun1()
print("f2:", f2())
print("f2:", f2())

输出
f1:     2
f1:     3
f2:     2
f2:     3

示例
string = "Lua Tutorial"
-- 查找字符串
print(string.find(string,"Tutorial"))
reversedString = string.reverse(string)
print("新字符串为",reversedString)

示例
string = "Lua Tutorial" 
-- 查找字符串 
print(string.find(string,"Tutorial"))
reversedString = string.reverse(string)
print("新字符串为",reversedString)
以上代码执行结果为:
5    12
新字符串为    lairotuT auL
Powered by emlog  蜀ICP备18021003号-1   sitemap

川公网安备 51019002001593号