阅读 199

Lua 入门教程

Lua简介

Lua作为一种脚本语言(解释型语言),号称性能最高的脚本,被广泛应用在很多需要性能的地方,比如nginx,游戏脚本,OpenResty等等。在我的项目agent中,使用lua脚本实现了任务处理逻辑。任务执行器在接收到任务时选择对应的lua脚本执行任务,与执行器进行解耦,同时支持热更新。

Lua入门

安装

Lua的安装非常简单,如果是Linux系统,则将make macosx test替换掉make linux test

curl -R -O http://www.lua.org/ftp/lua-5.3.5.tar.gz
tar zxf lua-5.3.5.tar.gz
cd lua-5.3.5
make linux test
复制代码

hello world

从最简单的hello world入门

$ lua
Lua 5.3.5  Copyright (C) 1994-2018 Lua.org, PUC-Rio
> print("hello world")
hello world
复制代码

类型

nil

nil是一种类型,可以理解为NULL,它的主要功能是用于区别其他任何值,将nil赋予给一个全局变量相当于对它进行删除。

boolean

boolean类型有两个可选值:false和true。Lua将false和nil视为假,将其他值视为真,不同于其他脚本语言,数字零和空字符串也视为真。

number

number类型用于表示实数,Lua没有整数类型,只有double型。

string

Lua完全采用8位编码,字符串是不可变的值。

> str="hello world"
> print(str)
hello world
复制代码

Lua还可以用一对匹配的双方括号来界定一个字符串。

> str=[[
>> print("hello world")
>> hello world
>> ]]
> print(str)
print("hello world")
hello world
复制代码

table

table类型实现了关联数组,是一种具有特殊索引方式的数组,可以通过整数,字符串或其他类型的值来索引,基于table,可以用来表示普通数组,符号表,集合,记录,队列和其他数据结构,Lua也通过table来表示模块(module)、包(package)和对象(object)。

array = {}
array[1]=1
array["2"]=2
array[3]="3"
复制代码

function

Lua中,函数是作为第一类值",可以存储在变量里,可以通过参数传递给其他函数,还可以作为其他函数的返回值。

local add = function(a,b)
    return a+b
end

function add1(a,b)
    return a+b
end

print(add(1,2))
复制代码

表达式

关系操作符

和其他语言一样,Lua支持<,>,<=,>=,==,~=。

逻辑操作符

逻辑操作有and,or和not。对于操作符and,如果第一个操作数为假,就返回第一个操作数,不然返回第二个操作数。对于操作符or,如果第一个操作数为真,就返回第一个操作数。

字符串连接

可以使用操作符..(两个点)

print("hello".."world")
复制代码

控制结构

if then else

a = 2
if a > 0 then
    print("a is positive")
end
复制代码

if then elseif then end

a = -1
if a > 0 then
    print("a is positive")
elseif a <0 then
    print("a is negative")
else
    error("a is zero")
end
复制代码

while

local i=1
local sum=0
while i < 10 do
    sum = sum +i
    i = i+1
end
print(sum)
复制代码

for

数字型for

语法如下所示,var从exp1变化到exp2,每次变化都以exp3作为步长,若不指定,则默认步长为1。#符号常用来指定数组的长度。

for var=exp1,exp2,exp3 do
    <execute>
end
复制代码

举个简单的例子

local i=1
local sum=0
for i=1,10,1 do
    sum = sum +i
    i = i+1
end
print(sum)
复制代码

泛型for

Lua的基础库提供了ipairs和pairs,两者都能用来遍历集合。两个的区别是

  • ipairs仅仅遍历值,按照索引升序遍历,索引中断就停止遍历。遇到nil就退出,它只能遍历到集合中出现的第一个不是整数的key。
  • pairs可以遍历集合中所有的key。
for i,v in ipairs(array) do
    print(v)
end

for i,v in pairs(array) do
    print(v)
end
复制代码

metatable与metamethod

在Lua中,每个值都有一套预定义的操作集合,通过元表可以修改一个值的行为,使其在面对一个非预定义的操作时执行一个指定的操作,假设元素a和b都是table类型,可以通过元表定义如何计算表达式a+b。

下面举了个简单的例子,用来实现两个table的相加

local string = require("string")
local format = string.format
//定义两个分数,fraction1为1/3,fraction2为2/3
local fraction1 = {denominator=3,numerator=1}
local fraction2 = {denominator=3,numerator=2}

//定义一个运算操作符
fraction_operator={}
//定义+的操作符重载
function fraction_operator.__add(f1,f2)
    res = {}
    res.denominator = f1.denominator * f2.denominator
    res.numerator = f1.numerator * f2.denominator + f2.numerator * f1.denominator
    return res
end
//为前面定义的两个table设置MetaTable
setmetatable(fraction1,fraction_operator)
setmetatable(fraction2,fraction_operator)

print(getmetatable(fraction1))
print(getmetatable(fraction2))

local fraction3 = fraction1 + fraction2
print(format("num:%d,den:%d",fraction3.numerator,fraction3.denominator))
复制代码

Lua内部约定的MetaMethod

__add(a, b)                     对应表达式 a + b
__sub(a, b)                     对应表达式 a - b
__mul(a, b)                     对应表达式 a * b
__div(a, b)                     对应表达式 a / b
__mod(a, b)                     对应表达式 a % b
__pow(a, b)                     对应表达式 a ^ b
__unm(a)                        对应表达式 -a
__concat(a, b)                  对应表达式 a .. b
__len(a)                        对应表达式 #a
__eq(a, b)                      对应表达式 a == b
__lt(a, b)                      对应表达式 a < b
__le(a, b)                      对应表达式 a <= b
__index(a, b)                   对应表达式 a.b
__newindex(a, b, c)             对应表达式 a.b = c
__call(a, ...)                  对应表达式 a(...)
复制代码

参考

coolshell.cn/articles/10…

Lua程序设计第二版