Lua入门

Categories:

Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。


环境安装

Linux

curl -R -O http://www.lua.org/ftp/lua-5.3.0.tar.gz
tar zxf lua-5.3.0.tar.gz
cd lua-5.3.0
make linux test
make install

MaxOS

curl -R -O http://www.lua.org/ftp/lua-5.3.0.tar.gz
tar zxf lua-5.3.0.tar.gz
cd lua-5.3.0
make macosx test
make install

Windows

安装SciTE 本地下载

SciTE使用:

打开SciTE,编写代码,保存为lua格式文件,F5运行

SciTE编码:

Options→Open User Options File→添加

code.page=65001
output.code.page=65001

基本语法

注释

单行注释

--

多行注释

--[[]]

标识符/变量

不要使用下划线加大写字母,不允许使用@、$、%,区分大小写

关键词

and、break、do、else、elseif、end、false、for、function、if、in、local、nil、not、or、repeat、return、then、true、until、while

下划线加大写字母(_VERSION)用于Lua内部全局变量

全局变量

默认情况,变量是全局变量,全局变量不需要声明,变量赋值后即为全局变量,删除变量,只需赋值nil即可

数据类型

变量不用定义类型,只需要为变量赋值

  • nil:无效值(在条件表达式中相当于false)
  • boolean:true和false
  • number:双精度浮点数
  • string:字符串可使用单引号或双引号
  • function:函数
  • userdata:存储在变量中的C数据结构
  • thread:线程
  • table:关联数组,数组索引可以是数字、字符串或表类型(多维数组)

使用type函数测试变量或值的类型

print(type(x))

nil

表示没有任何有效值,对于变量和数组起到删除值的作用

比较nil类型时需要使用双引号

type(x)=="nil"

对值进行nil比较时不需要双引号

print(x == nil)

boolean

Lua语言把false和nil作为假,其他都为真

number

默认之后双精度类型,可在luaconf.h里定义

数字与字符串进行算数操作时,Lua会将数字字符串转换成数字

print("1"+1)
输出:2

string

除单引号和双引号外,还可以使用双方括号表示

x=[[x]]

字符串连接使用..

print("a".."b")

使用数字连接时,必须在数字后面加上空格

print(1 .. 2)

字符串计算长度使用#

print(#"abcd")

table

默认索引从1开始,没有固定长度,自动增长

计算数组长度使用#

function

调用函数时传入值必须大于等于函数定义值

变量

类型

变量有三种类型

全局变量:Lua中的变量全是全局变量

局部变量:使用local声明的变量

表中的域

赋值

使用等号(=)赋值

可多变量同时赋值,当变量个数大于值的个数时,会用nil补位,当变量个数小于值的个数时,多余值会忽略

a,b=1,2

赋值时会先计算右边然后再赋值

a,b=1,2
a,b=b,a

索引

table的索引使用[],当索引为字符串时可以使用.

t = {k,"v"}
print(t["k"])
print(t.k)

循环

while

while(条件)
do
    执行体
end

for

for var,exp1,exp2,exp3
do
    执行体
end

exp3可以省略,默认循环方式为+1

for迭代

通过迭代器遍历值

a={"a","b","c"}
for i,v in ipairs(a)
do
    print(i,v)
end

使用ipairs函数迭代数组

repeat...until

repeat
    执行体
until(条件)

break:退出循环语句

流程

if

if(boolean)
then
    执行体
end

if...else

if(boolean)
then
    执行体
else
    执行体
end

if...elseif...else

if(boolean)
then
    执行体
elseif(boolean)
then
    执行体
else
    执行体
end

函数

作用域 function 函数名(参数)
    函数体
    return 返回值
end

函数名可省略

函数可赋值给变量

函数可以多返回值

可变参数使用...,使用select函数获取可变参数个数和参数值

select("#",...)
select(i,...)

固定参数和可变参数同时存在,固定参数在前

运算符

算数运算符

+(加)、-(减)、*(乘)、/(除)、%(取余)、^(乘幂)、-(负号)

关系运算符

==(等于)、~=(不等)、>(大于)、<(小于)、>=(大于等于)、<=(小于等于)

逻辑运算符

and(与)、or(或)、not(非)

a,b=true,ture
if(a and b)         true
if(a or b)          true
if(not(a and b))    false

其他运算符

..(连接运算符)、#(一元运算符,返回字符串或表的长度)

字符串

转义字符

\a(响铃)、\b(退格)、\f(换页)、\n(换行)、\r(回车)、\t(制表符)、\v(垂直制表符)、\\(一个反斜线)、\'(一个单引号)、\0(空字符)

字符串操作

string.upper(argument):全部转为大写字母

string.lower(argument):全部转为小写字母

string.gsub(mainString,findString,replaceString,num):字符串替换,mainString要替换的字符串,findString被替换的字符,replaceString要替换的字符,num提花你次数(可省略则全部替换)

string.gsub("abcabcabc","a","z",2)

string.find(str,substr,[init,[end]]):字符串查找,第三个参数为索引(起始位置)

string.find("abcdefg","cd",1)

string.reverse(arg):字符串反转

string.format(...):格式化字符串

string.char(arg)/string.byte(arg[,int]):char将整型数字转为字符,byte将字符转为整型数字,第二个参数为索引(默认为1,-1为最后一位)

string.len(arg):字符串长度

string.rep(string,n):复制字符串,n为次数

..:连接字符串

string.gmatch(str,pattern):字符串迭代器,返回符合pattern的子串

for word in string.gmatch("Hello World", "%a+") do print(word) end

string.match(str,pattern,init):字符串匹配,init为索引(起始配置)

string.sub(str,start,end):字符串截取,包含起始和结束位置

字符串格式化

string.format()函数生成特定格式字符串,函数第一个参数是格式,之后的参数是对应数据

转化数字

%c(ASCII码表中对应字符)、%d/%i(有符号的整数)、%o(八进制)、%u(无符号的整数)、%x(十六进制小写字母)、%X(十六进制大写字母)、%e(科学计数法小写字母)、%E(科学计数法大写字母)、%f(浮点数)、%g/%G(%e、%E、%g、%G、%f中较短的一个)

转发字符

%q(可安全被Lua编译器读入格式)、%s(给定的参数格式)

%后参数

符号:一个+表示其后的数字显示正号

占位符:一个0,指定了字符串宽度时占位用

对齐标识:默认右对齐,使用-号可改为左对齐

宽度数值

小数位数/字串裁切:保留小数部分n位/字符串前n位

string.format("%+d",1) --> +1
string.format("%02d",1) --> 01
string.format("%0.2f",1.2) -->1.20
string.format("%0.1s","Hello") -->H

匹配

print(string.sub("Hell123o",string.find("Hell123o","%d%d%d")))

匹配字符:^$()%.[]*+-?与自身匹配,字符类用大写时,表示与非此字符类的字符匹配

.(与任何字符匹配)、%a(与任何字母匹配)、%c(与任何控制符匹配\n)、%d(与任何数字匹配)、%l(与任何小写字母匹配)、%p(与任何标点匹配)、%s(与空白字符匹配)、%U(与任何大写字母匹配)、%w(与任何字母/数字匹配)、%x(与任何十六进制数匹配)、%z(与任何代表0的字符匹配)

数组

数组索引从1开始,也可以指定0开始,还可以以负数为索引

赋值初始化数组时,如果key相同,会覆盖

迭代器

for迭代器

for k, v in pairs(t) do
    print(k, v)
end

pairs以key、value形式返回,ipairs以index、value形式返回(如果table有key则不返回)

将表a赋值给表b后,a和b中都指向同一内存,当b中值发生变化,a中值也同样发生变化,当a为nil时,b仍有值

常用操作方法

table.concat(table[,sep[,start[,end]]]):表连接,arg1:表,arg2:指定连接字符,arg3:起始索引,arg4:结束索引

print(table.concat({"a","b","c"},"+",2,3)) -->b+c

table.insert(table,[pos,]value):表插入,arg1:表,arg2:插入索引,arg3:插入值

table.insert({"a","b","c"},2,"d") -->{"a","d","b","c"}

table.maxn(table):返回数组中最大值索引,Lua5.2以弃用

table.remove(talbe[,pos]):返回指定索引值并删除该索引的元素,arg2可选,默认为table长度即最后一位

table.sort(sort[,comp]):数组排序,默认升序

模块与包

模块类似于一个封装库,模块由变量、函数等组成的table

module={}
module.constant = "常量"
function module.func1()
	print("公有函数")
end
local function func2() --私有函数不能写模块名
	print("私有函数")
end
function module.func3()
	func2()
end
return module

加载模块

require("模块名")
require"模块名"
local m = require("模块名") --别名加载

调用模块

print(module.constant)
module.func1()
module.func3()

元表

简单理解为表关联

setmetatable(table,metatable):对指定table设置元表,如果元表中存在__metatable键值,setmetatable会失败

getmetatable(table):返回对象的元表

__index:metatable常用键,当访问table是如果键没有值,则会寻找该table的metatable中的__index键

单纯用setmetatable关联表时 table中并不会有键值,而使用__index关联时,table中也不会有键值,但会到metatable中查找

t1={1,2,3}
t2={}
setmetatable(t2,t1)
print(t1[1]) -->1
print(t2[1]) -->nil
t3={}
setmetatable(t3,{__index=t1})
print(t3[1]) -->1

__newindex:metatable常用键,对table添加键值时会保存到metatable中,使用__newindex关联时,table中没有值时,不会去metatable中查找

t1={}
t2={k1="v1"}
setmetatable(t2,{__newindex=t1})
print(t1.k1) -->nil
print(t2.k1) -->v1

t2.k2 = "v2"
print(t1.k2) -->v2
print(t2.k2) -->nil

I/O

打开文件语句

file = io.open(filename [, mode])

mode值

r(只读,文件必须存在)

w(打开只写文件,会清空文件内容)

a(追加形式打开只写文件,不会清空文件内容)

r+(读写,文件必须存在)

w+(打开可读写文件,会清空文件内容)

a+(追加形式打开读写文件,不会清空文件内容)

b(二进制文件)

+(即可读也可写)