这是我在学习Lua时记录的一些信息,包含我学习时的代码和记录的函数功能表格。
Lua安装
环境:Centos7.5
yum update -y
yum install lua -y
Lua笔记
脚本编程
通过yum安装的lua默认路径在/usr/bin/lua
。
创建及运行命令:
mkdir learn_lua
cd learn_lua
vim hello.lua
chmod +x hello.lua
./hello.lua
hello.lua
#/usr/bin/lua
print("hello")
基本语法
注释
-- 单行注释
--[[
多行注释
--]]
标志符
与其他语言一样。
首字符A-Z|a-z|_开头。
_A-Z开头一般不用,因为一般是Lua保留字。
关键字
and break do if else elseif end false for function in local nil not or repet return then true until while
全局变量
默认情况下,所有变量都是全局的。
变量可以直接赋值,不需要事先声明。访问未赋值的变量显示值为nil。
print(a)
a=1
print(a)
输出如下
nil
1
数据类型
nil
nil表示空。
nil比较时要加上引号。
print(b)
print(type(b)=='nil')
输出
nil
true
把一个变量赋值为nil意味着删除了该变量。
a=2
print(a)
a=nil
print(a)
输出
2
nil
boolean布尔
在Lua中false和nil为假,其他都为真。
number数字
Lua中只有一种数字类型double双精度类型。
数字有以下写法:
print(1)
print(0.1)
print(2e+2)
输出
1
0.1
200
string字符串
字符串由单引号或双引号包裹,也可以由[[]]包裹。
a='a'
b="b"
c=[[测试文字]]
print(a)
print(b)
print(c)
输出
a
b
测试文字
字符串连接使用..。
print(a..b)
输出
ab
当一个字符串中只有数字时,可以与数字作数学运算。
当两个数字使用字符串连接符..拼接时,中间要有空格才能成功拼接,例如2..2拼接不成功,2 .. 2拼接成功。
print("2"+2)
print("2"+"2")
print(2 .. 2)
输出
4
4
22
'#'用来计算字符串长度。
print(#"1234")
输出
4
table表
table是一种类似json的结构,可以添加单独的元素,也可以添加键值对,使用pairs(table)来遍历键值对表。
tb = {
name="水果",
child1="苹果",
child2="菠萝
}
print(tb.name)
for k,v in pairs(tb) do
print("key="..k.."value="..v)
end
输出
水果
key=child2value=菠萝
key=namevalue=水果
key=child1value=苹果
当成一维数组使用时,Key默认为数字递增,起始值为1,使用ipairs(table)来遍历数组。
表和数组的区别在于使用ipairs和pairs函数分别遍历,pairs能够完全显示数组和表的所有元素,但是ipairs不能显示key不为字符和数字的元素。
tb={"a","b","c"}
for k,v in pairs(tb) do
print("key="..k.."value="..v)
end
输出
key=1value=a
key=2value=b
key=3value=c
function函数
和其他语言中的函数一样。函数也可以存在变量里。
a=function(e)
return e
end
print(a(1))
输出
1
由于支持函数存在变量里,所以支持匿名函数调用。
a = function(e)
print(e)
end
function b(x,func)
func(x)
end
b(1,a)
输出
1
变量
Lua的变量有三种类型,全局变量、局部变量、表中的域。
Lua中的变量默认都是全局变量,除非用local显式的将一个变量定义为局部变量。局部变量的作用域从声明位置到语句块结束。
a=1
local b=2
print(a,b)
do
a=2
b=3
local d=5
print(a,b,d)
end
print(a,b,d)
输出
1 2
2 3 5
2 3 nil
赋值语句
Lua可以对多个变量同时赋值。当变量个数大于值的个数时,不足的值会以nil值补齐;当变量个数小于值的个数时,多余的值会被抛弃。如果要对多个变量赋值,需要依次列出多个变量的值。
a=1
b=2
a,b=b,a
print(a,b)
a,b=1,2
print(a,b)
a=1,2
print(a)
a,b,c=1,2
print(a,b,c)
输出
2 1
1 2
1
1 2 nil
多值赋值常用来交换变量的值,或者将函数调用返回给变量。
function num()
return 9,10
end
a,b=num()
print(a,b)
输出
9 10
索引
table内的元素访问可以使用数组形式,也可以使用.来访问。
tb={
miantiao="面条",
tudou="土豆"
}
print(tb.miantiao,tb["tudou"])
输出
面条 土豆
循环
for循环
泛型for循环
tb={
miantiao="面条",
tudou="土豆"
}
for k,v in pairs(tb) do
print(k,v)
end
输出
tudou 土豆
miantiao 面条
数值型for循环
数值型for循环有三个参数,举例for start,end,step do,依次是开始,结束,步长,步长可以省略,省略后步长默认为1。
for i=1,10,2 do
print(i)
end
输出
1
3
5
7
9
while循环
a=10
while(a>1)
do
print(a)
a=a-1
end
输出
10
9
8
7
6
5
4
3
2
注意lua不支持a--这样的写法,只能写作a=a-1。
repeat until循环
a=10
repeat
print(a)
a=a-1
until(a<2)
输出
10
9
8
7
6
5
4
3
2
lua支持循环嵌套。
流程控制
function zero(a)
if(a>0)
then
print(a,">0")
elseif(a<0)
then
print(a,"<0")
else
print(a,"=0")
end
end
zero(1)
zero(-1)
zero(0)
输出
1 >0
-1 <0
0 =0
函数
lua支持匿名函数,支持多返回值。
print("---")
--匿名函数
f = function(e)
print(e)
end
--匿名函数调用
function p(num,fun)
fun(num)
end
p(1,f)
--多返回值
function mutireturn()
return 1,2,3
end
print(mutireturn())
输出
---
1
1 2 3
lua支持可变参数。
select("#",...)返回传入可变参数的数量。
select(n,...)返回从第n个开始到最后的可变参数的数组。
function mutiexp(...)
for i,v in ipairs {...} do
print(i,v)
end
print(select("#",...))
print(select(2,...))
end
mutiexp(1,"b",3,4,5,"text")
输出
1 1
2 b
3 3
4 4
5 5
6 text
6
b 3 4 5 text
运算符
运算符列表(按照优先级排序)
运算符 | 说明 |
---|---|
^ | 乘幂,例如:2^2 |
not | 逻辑运算符,非,例如:not(true and false) |
- | 取负,例如:-1 |
* | 乘号 |
/ | 除号 |
+ | 加号 |
- | 减号 |
.. | 字符串连接符,例如: "1".."2" |
< | 小于号 |
> | 大于号 |
<= | 小于等于号 |
>= | 大于等于号 |
~= | 不等于号 |
== | 等于号 |
and | 逻辑运算符,和,例如:true and false |
or | 逻辑运算符,或,例如:true or false |
# | 求字符串字符总数,返回number,例如:#"123" |
字符串
字符串函数
记录一些字符串函数,以备查用。
函数 | 功能 | 示例 | 返回值 |
---|---|---|---|
string.upper() | 字符串转为大写 | string.upper("aBcde") | string 返回大写后的字符串 |
string.lower() | 字符串转为小写 | string.lower("AbCDE") | string 返回小写后的字符串 |
string.gsub() | 字符串替换 | 替换一次CD:string.gsub("ABCDCDS","CD","NN",1),替换全部CD:string.gsub("ABCDCDS","CD","NN") | string number 返回值为替换后的字符串、替换次数 |
string.find() | 字符串查找 | string.find("ABCDEF","BC") | number number 返回子串在字符串中第一次出现的起始位置和结束位置。位置说明:例:A字符的位置为1。 |
string.reverse() | 字符串反转 | string.reverse("Lua") | string 返回反转后的字符串 |
string.format() | 字符串格式化 | string.format("number is %d",2) | string 返回格式化后的字符串 |
string.char() | ASCII十进制数字转换为字符串 | string.char(65,66,67) | string 返回ASCII十进制数字转换为字符后连接在一起的字符串 |
string.byte() | 字符串首字母/指定字母转换为十进制ASCII | string.byte("ABCD") string.byte("ABCD",4) | number 返回指定字母的ASCII码 |
string.len() | 字符串长度 | string.len("ABC") | number 返回字符串长度 |
string.rep() | 字符串重复 | string.rep("ABC",2) | string 返回重复的字符串 |
string.gmatch() | 字符串迭代器函数 | for word in string.gmatch("ABCD E F","%a+") do print(word) end | string 在原字符串中查找每次迭代返回一个与模式匹配的字符串 |
string.match() | 字符串匹配函数 | string.match("A BC D","%a+") | 多个string 返回匹配的字符串 |
匹配模式
记录一些字符串匹配模式,以备查用。
字符 | 模式 |
---|---|
.(点) | 与任何字符配对 |
%a | 与任何字母配对 |
%c | 与任何控制符配对(例如n) |
%d | 与任何数字配对 |
%l | 与任何小写字母配对 |
%p | 与任何标点(punctuation)配对 |
%s | 与空白字符配对 |
%u | 与任何大写字母配对 |
%w | 与任何字母/数字配对 |
%x | 与任何十六进制数配对 |
%z | 与任何代表0的字符配对 |
%x | (此处x是非字母非数字字符): 与字符x配对. 主要用来处理表达式中有功能的字符(^$()%.[]*+-?)的配对问题, 例如%%与%配对 |
[数个字符类] | 与任何[]中包含的字符类配对. 例如[%w_]与任何字母/数字, 或下划线符号(_)配对 |
1 | 与任何不包含在[]中的字符类配对. 例如2与任何非空白字符配对 |
- 单个字符类匹配该类别中任意单个字符;
- 单个字符类跟一个 '*', 将匹配零或多个该类的字符。 这个条目总是匹配尽可能长的串;
- 单个字符类跟一个 '+', 将匹配一或更多个该类的字符。 这个条目总是匹配尽可能长的串;
- 单个字符类跟一个 '-', 将匹配零或更多个该类的字符。 和 '*' 不同, 这个条目总是匹配尽可能短的串;
- 单个字符类跟一个 '?', 将匹配零或一个该类的字符。 只要有可能,它会匹配一个;
- %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' 一样。
数组
支持多维数组。数组的第一个元素的下标是1。
a={"a","b","c","d"}
print(a[1])
b={}
b[1]={}
b[2]={}
b[1][1]=0
b[1][2]=1
b[2][1]=3
b[2][2]=4
print(b[2][1])
输出
a
3
迭代器
迭代器可以遍历集合中的每个元素。
无状态的迭代器
迭代器有两个参数,状态常量和控制变量,需要返回两个参数,一个控制变量,一个处理后的值。
function sq(con,var)
if(var<con)
then
var=var+1
return var,var*var
end
end
for var,varvar in sq,3,0 do
print(var,varvar)
end
输出
1 1
2 4
3 9
多状态的迭代器
多状态迭代器使用table保存状态常量,控制变量也可以放在table里,因此,多状态迭代器只需要一个变量传入。
a={"a","b","c"}
function d(collection)
local index=0
local len=#collection
return function()
index=index+1
if index<=len
then
return collection[index]
end
end
end
for e in d(a) do
print(e)
end
输出
a
b
c
table表
table表函数
记录一些table表函数,以备后用。
函数 | 功能 | 示例 | 返回值 |
---|---|---|---|
table.concat() | 把table里的元素连接成字符串 | table.concat({"a","b"},",",1,2) | string 返回连接后的字符串 |
table.insert() | 在指定位置插入一个元素,可不指定位置,默认插入在末尾 | table.insert({},2,"a") | table 返回插入后的table |
table.remove() | 删除指定位置的一个元素,可不指定位置,默认删除最后一个元素 | table.remove({"a"},1) | table 返回删除后的table |
table.sort() | 排序,按照字母表和数字顺序对table排序,可指定升序降序 | table.sort({}) | table 返回排序后的table |
模块与包
模块的创建与使用
创建模块就是新建一个table,把字段和函数存进table,再返回这个table即可。
moudle.lua
moudle={}
moudle.con="定义一个常量"
function moudle.fun()
return "定义一个函数"
end
local function private_fun()
print("这是一个私有函数")
end
function moudle.use_private_fun()
private_fun()
print("私有函数只能由全局函数调用,外部不可直接使用")
end
return moudle
加载模块使用require()函数。
use_moudle.lua
require("moudle")
print(moudle.fun())
print(moudle.con)
也可以给加载的模块一个别名,便于使用。
use_moudle_cname.lua
m=require("moudle")
m.use_private_fun()
加载机制
Lua会尝试从以下路径加载文件,不在这些路径中的文件无法加载。
- package.path中的文件
在centos中,package.path路径为:
./?.lua;/usr/share/lua/5.1/?.lua;/usr/share/lua/5.1/?/init.lua;/usr/lib64/lua/5.1/?.lua;/usr/lib64/lua/5.1/?/init.lua
- 自定义的LUA_PATH
export LUA_PATH="~/lua/?.lua;"
- 当前文件夹
推荐在当前文件夹下写完所有lua模块,便于加载。
Lua中还可以加载c包。
metatable元表
元表是对table的一种扩展,元表本身也是一个table。给一个table设置元表使用setmetatable(),获取一个table的元表使用getmetatable()。
setmetatable()返回的是被设置元表的table。
tb={}
metatb={}
setmetatable(table,metatb)
metatb_tmp=getmetatable(table)
__index键
当一个table中没有一个键时,Lua会寻找该table的元表的__index键,并在其中试图找到该键。
使用__index键可以指定一个新的table扩展原table的键值对。
tb={}
other={con="ab"}
metatb=setmetatable(tb,{__index=other})
print(tb.con)
print(other.con)
print(metatb.con)
输出
ab
ab
ab
如果__index中存的是一个函数,那么操作的table和table请求的键名要当做参数传给这个函数。
tb={}
metatb=setmetatable(tb,{
__index=function(tb,key)
return key
end
})
print(tb.a)
print(metatb.a)
输出
a
a
__newindex
__index在查找table值的时候使用。
__newindex则在新建table值的时候调用,相当于拦截了所有对table的新添加键值对传给元表。
tb={key1="a"}
metatb={}
tb=setmetatable(tb,{__newindex = metatb})
tb.key2="b"
print(tb.key2,metatb.key2)
tb.key1="c"
print(tb.key1,metatb.key1)
输出
nil b
c nil
coroutine协同程序
coroutine与线程类似,拥有独立的堆栈、局部变量、指针指令,同时又与其他coroutine共享全局变量和其他大部分东西。
coroutine与线程的区别是,拥有多个线程的程序可以在同时运行几个线程,但是coroutine需要互相协调运行。
在任一指定时刻只能有一个coroutine运行,并且这个coroutine只有在明确被要求挂起时才会挂起。
在等待同一个线程锁的多个线程类似coroutine。
函数 | 功能 |
---|---|
coroutine.create() | 创建coroutine,参数是一个函数。 |
coroutine.resume() | 重启/继续corourine,第一个参数是coroutine实例,第二个参数为coroutine初始化时定义的函数的参数。 |
coroutine.yield() | 挂起coroutine。 |
coroutine.status() | 返回coroutine的状态,有三个状态:dead,suspend,running |
coroutine.running() | 返回正在运行的coroutine线程的线程号 |
使用示例:
co=coroutine.create(
function(e)
print(e)
print(coroutine.running(co))
end
)
coroutine.resume(co,2)
print(coroutine.status(co))
输出
2
thread: 0xa8c520
dead
面向对象
Student={
name="default",
age=18
}
function Student:new(obj,name)
obj=obj or {}
setmetatable(obj,self)
self.__index = self
name = name or "default name"
self.name = name
return obj
end
function Student:printName()
print(self.name)
end
stu1 = Student:new(nil,"小明")
stu1:printName()
输出
小明
垃圾回收
Lua采用了自动垃圾回收。
Lua使用了一个垃圾收集器来收集所有不会被用到的对象。
垃圾收集器默认以内存分配的2倍速工作,这个速度是可调的。
函数 | 功能 |
---|---|
collectgarbage("collect") | 使用函数手动开启一次完整的垃圾收集。 |
collectgarbage("restart") | 重启垃圾收集器 |
以上即是我学习Lua的笔记,我的邮箱是wubo@wubo.net.cn
,欢迎和我讨论。
Comments | NOTHING