Lua基本语法
1 Lua介绍
起源:
Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放,其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。Lua 是由巴西里约热内卢天主教大学的 PUC-Rio 团队设计、实施和维护。
特性:
- 轻量级:它用标准C语言编写并以源代码形式开发,编译后仅仅一百余 k,可以很方便地嵌入别的程序里;
- 可扩展性
- 跨平台
- 开源
应用场景:
- 游戏开发
- 单机应用
- Web
- 数据库扩展
- 开发安全系统

# Linux安装Lua
wget http://www.lua.org/ftp/lua-5.2.3.tar.gz
tar zxf lua-5.2.3.tar.gz
cd lua-5.2.3
make linux test
2 基本语法
2.1 变量定义
全局变量:除非显示的声明一个局部变量,否则所有的变量都被默认当作全局变量;
局部变量:如果我们将一个变量定义为局部变量,那么这些变量的作用域就被限制在函数内
表字段:一种特殊的变量,可以是除了 nil 以外的所有类型,包括函数
local d, f = 5, 10 --声明局部变量d, f
d, f = 5, 10; --声明全局变量d, f
d, f = 10 --声明全局变量d, f, 其中f的值是 nil--
2.2 数据类型
| 值类型 | 描述 |
| nil | 用于区分值是否有数据,nil 表示没有数据。 |
| boolean | 布尔值,有真假两个值,一般用于条件检查。 |
| number | 数值,表示实数(双精度浮点数)。 |
| string | 字符串。 |
| function | 函数,表示由C或者Lua写的方法 |
| userdata | 表示任意C数据。 |
| thread | 线程,表示独立执行的线程,它被用来实现协程。 |
| table | 表,表示一般的数组,符号表,集合,记录,图,树等等,它还可以实现关联数组。它可以存储除了 nil 外的任何值。 |
print(type("What is my type")) --> string
t = 10
print(type(5.8 * t)) --> number
print(type(true)) --> boolean
print(type(print)) --> function
print(type(type)) --> function
print(type(nil)) --> nil
print(type(type(ABC))) --> string
2.3 循环与流程
循环类型
| 循环类型 | 描述 |
| while循环 | 先检测条件,条件为真时再执行循环体,直到条件为假时结束。 |
| for循环 | 执行一个语句序列多次,可以简化管理循环变量的代码。 |
| repeat...until循环 | 重复执行一组代码语句,直到 until 条件为真为止。 |
| 嵌套循环 | 可以在一个循环语句中再使用一个循环语句。 |
循环控制
| 循环控制语句 | 描述 |
| break | break 语句结束循环,并立即跳转至循环或 switch 语句后的第一条语句处开始执行。 |
while(condition)
dostatement(s)
endfor init, max/min value, increment
dostatement(s)
endrepeatstatement(s)
until(condition)
2.4 流程控制
| 语句 | 描述 |
| if 语句 | if 语句中包含一个布尔表达式和一个或多个语句。 |
| if...else 语句 | if 语句也可以选择和 else 语句一起使用。当条件为假时,则执行 else 语句。 |
| 嵌套 if 语句 | 在 if 语句或者 else if 语句内使用 if 或者 else if |
2.5 函数
固定参数
optional_function_scope function function_name(argument1, argument2, argument3)function_bodyreturn result_params_comma_separated
end
可变参数
function average(...)result = 0local arg = {...}for i, v in ipairs(arg)doresult = result + vendreturn result/#arg
endprint("The average is", average(10, 5, 3, 4, 5, 6))
输出
The average is 5.5
2.6 字符串
-- 单引号字符串
string1 = 'Lua'
print("\"String 1 is\"", string1)-- 双引号字符串
string2 = "English"
print("String 2 is", string2)-- [[""]]之间的字符串
string3 = [["Lua English"]]
print("String 3 is", string3)
常用的字符串操作
| S.N. | 函数及其功能 |
| 1 | string.upper(argument):将输入参数全部字符转换为大写并返回 |
| 2 | string.lower(argument):将输入参数全部字符转换为小写并返回 |
| 3 | string.gsub(mainString, findString, replaceString):将 mainString 中的所有 findString 用 replaceString 替换并返回结果。 |
| 4 | string.strfind(mainString, findString, optionalStartIndex, optionalEndIndex):在主字符串中查找 findString 并返回 findString 在主字符串中的开始和结束位置,若查找失败则返回 nil。 |
| 5 | string.reverse(arg):将输入字符串颠倒并返回。 |
| 6 | string.format(...):返回格式化后的字符串。 |
| 7 | string.char(arg) 和 string.byte(arg):前者返回输出参数的代表的字符,后者返回输入参数(字符)的数值。 |
| 8 | string.len(arg):返回输入字符串的长度。 |
| 9 | string.rep(string, n):将输入字符串 string 重复 n 次后的新字符串返回。 |
| 10 | ..:连接两个字符串。 |
2.6.1 字符匹配
字符匹配
| 符号 | 描述 |
| .(点) | 与任何字符配对。 |
| %a | 与任何字母配对。 |
| %c | 与任何控制符配对(例如\n)。 |
| %d | 与任何数字配对。 |
| %l | 与任何小写字母配对。 |
| %p | 与任何标点(punctuation)配对 |
| %s | 与空白字符配对。 |
| %u | 与任何大写字母配对。 |
| %w | 与任何字母/数字配对。 |
| %x | 与任何十六进制数配对。 |
| %z | 与任何代表0的字符配对。 |
模式条目
- 单个字符类匹配该类别中任意单个字符;
- 单个字符类跟一个'*',将匹配零或多个该类的字符。这个条目总是匹配尽可能长的串;
- 单个字符类跟一个'+',将匹配一或多个该类的字符。这个条目总是匹配尽可能长的串;
- 单个字符类跟一个'-',将匹配零或更多个该类的字符。和'*'不同,这个条目总是匹配尽可能短的串;
- 单个字符类跟一个'?',将匹配零或一个该类的字符,只要有可能,它会匹配一个。
模式
模式指一个模式条目的序列。在模式最前面加上符号 '^' 将锚定从字符串的开始做匹配。在模式最后面加上符号'$'将使匹配过程锚定到字符串的结尾。如果 '^' 和 '$' 出现在其它位置,它们均没有特殊含义,只表示自身。
2.7 数组与迭代器
一维数组
array = {"Lua", "Tutorial"} -- 这里的数组是从下标1开始存值
for i = 0, 2 doprint(array[i])
end输出:
nil
Lua
Tutorial
多维数组
dw_array = {array1, array2, ..., arrayn}
无状态迭代器
普通函数
有状态迭代器
创建闭包
array = {"Lua", "Tutorial"}
function elementIterator (collection)local index = 0local count = #collection-- 返回闭包函数return function()index = index + 1if index <= countthen-- 返回迭代器的当前元素return collection[index]endend
endfor element in elementIterator(array) do print(element) end
2.8 表
表的初始化
-- 简单的表初始化
mytable = {}
-- 简单的表赋值
mytable[1] = "Lua"
-- 移除引用
mytable = nil
-- Lua 的垃圾回收机制负责回收内存空间
表常用函数
| S.N. | 方法与作用 |
| 1 | table.concat(table[, sep[, i[, j]]]):根据指定的参数合并表中的字符串。具体用法参考下面的示例。 |
| 2 | table.insert(table, [pos, ]value):在表中指定位置插入一个值。 |
| 3 | table.maxn(table):返回表中最大的数组索引。 |
| 4 | table.remove(table[, pos]):从表中移出指定的值。 |
| 5 | table.sort(table[, comp]):根据指定的(可选)比较方法对表进行排序操作 |
2.9 模块
模块概念:
Lua 中的模块与库的概念相似,每个模块都有一个全局唯一名字,并且每个模块都包含一个表。使用一个模块时,可以使用 require 加载模块。模块中可以包含函数和变量,所有这些函数和变量被表存储于模块的表中。模块中的表的功能类似于命名空间,用于隔离不同模块中的相同的变量名。
创建模块
local mymath = {}
-- 存储模块的表
function mymath.add(a, b)print(a / b)
end
-- 模块中的函数
return mymath
-- 返回模块
导入模块
mymathmodule = require("mymath")
mymathmodule.add(10, 20)
注意事项:
- 一般模块名与文件名称相同
- 模块和待运行的文件放在同一目录
- require 用于搜索 Lua 文件的路径是存放在全局变量 package.path,以 LUA_PATH 初始化
- 如果找过目标文件,则会调用 package.loadfile 来加载模块。否则,就会去找C程序库
2.10 元表与元方法
元表概念:
将一个表与另外一个表关联,通过元方法实现一些操作重载。
创建元表与获取元表:
- setmetatable(table, metatable):此方法用于为一个表设置元表。
- getmetatable(table):此方法用于获取表的元表对象。
mytable = setmetatable({}, {})
元方法
| 键 | 描述 |
| __add | 改变加法操作符的行为。 |
| __sub | 改变减法操作符的行为。 |
| __mul | 改变乘法操作符的行为。 |
| __div | 改变除法操作符的行为。 |
| __mod | 改变模除操作符的行为。 |
| __unm | 改变一元减操作符的行为。 |
| __concat | 改变连接操作符的行为。 |
| __eq | 改变等于操作符的行为。 |
| __lt | 改变小于操作符的行为。 |
| __le | 改变小于等于操作符的行为。 |
| __index | 当你通过键来访问 table 的时候,如果这个键没有值,那么 Lua 就会寻找该 table 的 metatable (假定有 metatable)中的 __index 键 |
| __newindex | 对新索引赋值,调用元方法 |
| __call | __call 元方法在 Lua 调用一个值时调用 |
mytable = setmetatable({key1 = "value1"}, {__index = function(mytable, key)if key == "key2" thenreturn "metatablevalue"elsereturn mytable[key] end end})
print(mytable.key1, mytable.key2)
2.11 协程
协程概念:
协程具有协同的性质,它允许两个或多个方法以某种可控的方式协同工作。在任何一个时刻,都只有一个协程在运行,只有当正在运行的协程主动挂起时,它的执行才会被挂起(暂停)。
协程函数
| S.N. | 方法和功能 |
| 1 | coroutine.create(f):用函数 f 创建一个协程,返回 thread 类型对象。 |
| 2 | coroutine.resume(co[, val1, ...]):传入参数(可选),重新执行协程 co。此函数返回执行状态,也可以返回其它值。 |
| 3 | coroutine.running():返回正在运行的协程,如果在主线程中调用此函数则返回 nil。 |
| 4 | coroutine.status(co):返回指定协程的状态,状态值允许为:正在运行(running),正常(normal),挂起(suspended),结束(dead)。 |
| 5 | coroutine.wrap(f):与前面 coroutine.create 一样,coroutine.wrap 函数也创建一个协程,与前者返回协程本身不同,后者返回一个函数。当调用该函数时,重新执行协程。 |
| 6 | coroutine.yield(...):挂起正在执行的协程。为此函数传入的参数值作为执行协程函数 resume 的额外返回值(默认会返回协程执行状态)。 |
2.12 文件
打开文件
file = io.open(filename[, mode])
| 模式 | 描述 |
| "r" | 只读模式,这也是对已存在的文件的默认打开模式。 |
| "w" | 可写模式,允许修改已经存在的文件和创建新文件。 |
| "a" | 追加模式,对于已存的文件允许追加新内容,但不允许修改原有内容,同时也可以创建新文件。 |
| "r+" | 读写模式打开已存在的文件。 |
| "w+" | 如果文件已存在,则删除文件中的数据;若文件不存在,则新建文件。读写模式打开。 |
| "a+" | 以可读的追加模式打开已存在的文件,若文件不存在,则新建文件。 |
隐式与显式操作
-- 只读模式打开文件
file = io.open("test.lua", "r")-- 将 test.lua 设置为默认输入文件
io.input(file)-- 打印输出文件的第一行
print(io.read())-- 关闭打开的文件
io.close(file)
-- 只读模式打开文件
file = io.open("test.lua", "r")-- 输出文件的第一行
print(file:read())-- 关闭打开的文件
file.close()
2.13 错误处理
assert(断言,如果不符合,则打印,退出程序)
assert(type(a) == "number", "a is not a number")
error
pcall(成功执行,否则 else)
if pcall(myfunction) thenprint("Success")
elseprint("Failure")
end
xpcall(错误时调用 handler 函数)
function myerrorhandler(err)print("ERROR:", err)
endstatus = xpcall(myfuction, myerrorhandler)
3 Example
turbo 的一个简单 demo
local turbo = ("turbo")
local HelloWorldHandler = class("HelloWorldHandler", turbo.web.RequestHandler)
function HelloWorldHandler:get()self:write({name = "deep", age = "18", sex = "M"})
end
turbo.web.Application({{"/user", HelloWorldHandler}}):listen(8888)
turbo.ioloop.instance():start()
redfish-core
-- 资源
local resource = require("redfish-resource")
resource.load_all_resource_table()
resource.load_route_method_map()-- 创建
local app = turbo.web.Application:new(route_table)-- 监听
local success, ret = pcall(turbo.web.Application.listen, app,
CONFIG.SERVICE_PORT, CONFIG.SERVICE_HOST, {max_header_size = 1024*1024*2,
streaming_multipart_bytes = 5*1024*1024})-- 启动
turbo.ioloop.instance():start()
