- table {:toc}
Lua 是一门小巧的编程语言,但麻雀虽小五脏俱全,而且与 C 语言的交互非常友好,所以有人称它是 “胶水语言”。最近在研究 nginx,另一个广泛应用的、基于 nginx 的开源项目 OpenResty 就是把 lua 嵌入到了 nginx 中,很有意思。于是就来学习一下 lua。
基本语法
单行注释用 --
,多行注释用
--[[
多行注释
--]]
数据类型
- nil 表示一个无效值(在条件表达式中相当于false)。
- boolean 包含两个值:false和true。
- number 表示双精度类型的实浮点数
- string 字符串由一对双引号或单引号来表示
- function 由 C 或 Lua 编写的函数
- userdata 表示任意存储在变量中的C数据结构
- thread 执行协同程序
- table 表或者数组
table 类型
在 Lua 里,table 的创建是通过"构造表达式"来完成,最简单构造表达式是{},用来创建一个空表。
local tbl1 = {}
local tbl2 = {"apple", "pear", "orange", "grape"}
另外,数组的索引可以是数字或者是字符串。比如有以下代码:
a = {}
a["key"] = "value"
key = 10
a[key] = 22
a[key] = a[key] + 11
最后 table a 中的内容是 (10, 33) 和 (key, value)
函数
和 go 之类的高级语言一样,lua 也有匿名函数,比如下面这样:
function testFun(tab,fun)
for k ,v in pairs(tab) do
print(fun(k,v));
end
end
tab={key1="val1",key2="val2"};
testFun(tab,
function(key,val)
return key.."="..val;
end
);
Lua 变量
连接一个字符串: a = "hello" .. "world"
。
t.i
当索引为字符串类型时, t.i = t[i]
循环
无论是 for 还是 while 循环,循环体都被包在 “do end” 之中。 看几个例子:
for
for var=exp1,exp2,exp3 do
<执行体>
end
或者
a = {"one", "two", "three"}
for i, v in ipairs(a) do
print(i, v)
end
while
while 循环比较容易记
while( a < 20 )
do
a = a+1
end
repeat until
这个是 lua 语言独有的循环方式,但它本质上就是 do{ }while
repeat
statements
until( condition )
if else
lua 中的 if 需要带上 “then”
if( 布尔表达式 1)
then
--[ 在布尔表达式 1 为 true 时执行该语句块 --]
elseif( 布尔表达式 2)
then
--[ 在布尔表达式 2 为 true 时执行该语句块 --]
else
--[ 如果以上布尔表达式都不为 true 则执行该语句块 --]
end
函数多值返回和可变参数
Lua函数可以返回多个结果值,比如string.find(),其返回匹配串"开始和结束的下标"。
这个比较有意思,在函数参数列表中使用三点 … 表示函数有可变的参数。
function add(...)
local s = 0
for i, v in ipairs{...} do
s = s + v
end
return s
end
print(add(3,4,5,6,7))
也可以通过 select("#",…) 来获取可变参数的数量:
function average(...)
result = 0
local arg={...}
for i,v in ipairs(arg) do
result = result + v
end
print("总共传入 " .. select("#",...) .. " 个数")
end
运算符
- and / or / not 逻辑运算符
~=
不等于..
连接两个字符串#
一元运算符,返回字符串或表的长度
字符串操作
列举 lua 内置的一些字符串操作函数,这部分内容比较细节,详细见此处
- string.upper()
- string.lower()
- string.gsub(mainString,findString,replaceString,num),mainString为要替换的字符串, findString 为被替换的字符,replaceString 要替换的字符,num 替换次数
- string.find (str, substr, [init, [end]])
- string.reverse(arg)
- string.format(…)
- string.char(arg) 和 string.byte(arg[,int]),char 将整型数字转成字符并连接, byte 转换字符为整数值
- string.len(arg)
- string.rep(string, n)
- string.gmatch(str, pattern),返回一个迭代器函数,每一次调用这个函数,返回一个在字符串 str 找到的下一个符合 pattern 描述的子串。如果参数 pattern 描述的字符串没有找到,迭代函数返回nil。
- string.match(str, pattern, init),只寻找源字串str中的第一个配对
其中有关模式匹配的正则表达式规则,详细内容见上面的链接。
多维数组
前面的例子都是一维数组,现在看看一个二维数组的例子:
array = {}
for i=1,3 do
array[i] = {}
for j=1,3 do
array[i][j] = i*j
end
end
-- 访问数组
for i=1,3 do
for j=1,3 do
print(array[i][j])
end
end
Lua 迭代器
如果 table tlb 是一个 k-v 结构的表,那么像下面这样迭代
for k, v in pairs(tbl) do
print(k, v)
end
如果 table 是一个一位数组,用 ipair() 就可以了。
array = {"Lua", "Tutorial"}
for key,value in ipairs(array)
do
print(key, value)
end
其他高级的 无状态的迭代器 或者 多状态迭代器,传送门
coroutine 协程
一个简单的例子展示用 lua coroutine 完成经典的 生产者-消费者 问题。
local newProductor
function productor()
local i = 0
while true do
i = i + 1
send(i) -- 将生产的物品发送给消费者
end
end
function consumer()
while true do
local i = receive() -- 从生产者那里得到物品
print(i)
end
end
function receive()
local status, value = coroutine.resume(newProductor)
return value
end
function send(x)
coroutine.yield(x)
-- x表示需要发送的值,值返回以后,就挂起该协同程序
end
-- 启动程序
newProductor = coroutine.create(productor)
consumer()