文章目录
- Lua 脚本
- 注释
- 关键字
- 变量
- 循环
- 函数
- 可变参数
- 运算符
- 字符串
- 数组
- 迭代器与表 (重点)
- 模块与包
前言:本文内容大部分摘抄自 菜鸟教程
Lua 语法学习推荐文章:CSDN - 董哥的黑板报
Lua 脚本
在代码开头添加:#!/usr/local/bin/lua
,然后给 xxx.lua 添加可执行权限即可。
注释
单行注释:
--
多行注释:
--[[]]
关键字
Lua 是动态类型语言,变量不需要类型定义,只需要为变量赋值,值可以存储在变量中,作为参数传递或结果返回。
注意事项:
- nil 类型表示一种没有任何有效值,对于全局变量和 table,nil 具有删除作用;另外,nil 作比较时应该加上双引号。
- Lua 把 false 和 nil 看作是 false,其他的都为 true,数字 0 也是 true。
- Lua 默认只有一种 number 类型 – double(双精度)类型。
- 字符串由一对双引号或单引号来表示,也可以用 2 个方括号 “[[]]” 来表示"一块"字符串。
- Lua 使用
..
进行字符串拼接,使用#
计算字符串长度。 - Lua 的表使用构造表达式进行初始化,类似于C++中的列表初始化 –
local table = {"apple", "pear", "orange", "grape"}
- Lua 表的索引从 1 开始
变量
Lua 变量有三种类型:全局变量、局部变量、表中的域。变量的默认值均为 nil。
Lua 中的变量全是全局变量,哪怕是语句块或是函数里,除非用 local 显式声明为局部变量。
注意事项:
-
Lua 可以对多个变量同时赋值,变量列表和值列表的各个元素用逗号分开
a, b = 10, 2*x <--> a=10; b=2*xa, b = 0, 1 a, b = a+1, a+1 print(a,b) --> 1 1
-
遇到赋值语句 Lua 会先计算右边所有的值 (等号右边的值) 然后再执行赋值操作 – 表达式右边是值而不是变量,所以我们可以这样进行交换变量的值:
a, b = b, a
-
在访问数组索引时,Lua 支持
[]
,也支持.
,便于字符串操作:> site = {} > site["key"] = "www.runoob.com" > print(site["key"]) www.runoob.com > print(site.key) www.runoob.com
循环
Lua 语言提供了以下几种循环处理方式:
注意:while 是在进入循环前检查条件,而 repeat…until 是在循环执行后再检查条件,即 repeat…until 相当于 C++ 中的 do…while.
特别注意:while(0) / repeat…until(0) 是死循环。
函数
Lua 编程语言函数定义格式如下:
optional_function_scope function function_name( argument1, argument2, argument3..., argumentn)function_bodyreturn result_params_comma_separated
end
- optional_function_scope: 该参数是可选的指定函数是全局函数还是局部函数,未设置该参数默认为全局函数,如果你需要设置函数为局部函数需要使用关键字 local。
- function_name: 指定函数名称。
- argument1, argument2, argument3…, argumentn: 函数参数,多个参数以逗号隔开,函数也可以不带参数。
- function_body: 函数体,函数中需要执行的代码语句块。
- result_params_comma_separated: 函数返回值,Lua语言函数可以返回多个值,每个值以逗号隔开。
重点:Lua 函数不需要定义返回值类型,且可以返回多个值,多个值之间使用逗号分隔。
可变参数
Lua 函数可以接受可变数目的参数,和 C 语言类似,在函数参数列表中使用三点 … 表示函数有可变的参数。
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)) --->25
我们可以将可变参数赋值给一个变量:
local args = {...}
我们可以通过如下方式来获取可变参数的数量:
local arg={...}
print(#arg)
print(select("#",...))
通常在遍历变长参数的时候只需要使用 {…},然而变长参数可能会包含一些 nil,那么就可以用 select 函数来访问变长参数:
- select(‘#’, …) 返回可变参数的长度。
- select(n, …) 用于返回从起点 n 开始到结束位置的所有参数列表。
function f(...)a = select(3,...) -->从第三个位置开始,变量 a 对应右边变量列表的第一个参数print (a)print (select(3,...)) -->打印所有列表参数
endf(0,1,2,3,4,5)
运算符
Lua 运算符中与 C/C++ 中不同的部分:
- 在 lua 中,/ 用作除法运算,计算结果包含小数部分,// 用作整除运算,计算结果不包含小数部分
- 在 lua 中,~= 是不等于判断,C/C++ 中则是 !=
- lua 中的逻辑运算符为 and or not,同样存在 “短路” 情况
- lua 不支持 ++ – += -= 操作
字符串
Lua 中的字符串使用 ''
或 ""
来表示,还可以使用 []
来表示一串字符。
与 C/C++ 中字符串不同的是,Lua 的字符串有自己的内部长度信息,不需要依赖 \0
这样的终止符,同时,Lua 字符串是不变的,改变字符串内容会直接创建新字符串,Lua 字符串也不支持 []
操作。
字符串部分操作 :
-方法 | 方法描述 |
---|---|
#str string.len(str) utf8.len(str) | 计算字符串长度 按 ASCII 编码计算字符串长度 计算包含中文的字符串长度 |
string.upper(str) | 字符串转大写 |
string.lower(str) | 字符串转小写 |
string.gsub(mainString,findString,replaceString,num) | 在字符串中替换,其中: mainString 为要操作的字符串 findString 为被替换的字符 replaceString 要替换的字符 num 替换次数(可以忽略,则全部替换) |
string.find (str, substr, [init, [plain]]) | 在一个指定的目标字符串 str 中搜索指定的内容 substr,如果找到了一个匹配的子串,就会返回这个子串的起始索引和结束索引,不存在则返回 nil。 init 指定了搜索的起始位置,默认为 1,可以一个负数,表示从后往前数的字符个数。 plain 表示是否使用简单模式,默认为 false,true 只做简单的查找子串的操作,false 表示使用使用正则模式匹配。 |
string.reverse(str) | 字符串反转 |
string.gmatch(str, pattern) | 返回一个迭代器函数,每一次调用这个函数,返回一个在字符串 str 找到的下一个符合 pattern 描述的子串。如果参数 pattern 描述的字符串没有找到,迭代函数返回nil。 |
string.match(str, pattern, init) | string.match()只寻找源字串str中的第一个配对. 参数init可选, 指定搜寻过程的起点, 默认为1。 |
string.sub(s, i [, j]) str:sub(i, [, j]) | 字符串截取 可以直接变量名后跟 :sub() |
数组
Lua 中并没有专门的数组类型,而是使用 table
来实现数组功能:
local arr = {1, 2, 3, 4, 5}
Lua 数组的索引从 1 开始,同时,数组大小是动态扩容的,因此不需要考虑越界访问和赋值的问题 – 越界访问返回 nil,越界赋值会自动扩容。
需要注意的是,与 C/C++ 不同,Lua 数组中的元素必须全部显示赋值,否则为 nil,不会像 C/C++ 那样自动初始化:
-- C/C++
int arr[5] = { 1 }; ==> 1,0,0,0,0
-- lua
arr = { 1, 2 }
arr[4] = 4 ==> 1,2,nil,4
一维数组:
-- 创建一个数组
local myArray = {10, 20, 30, 40, 50}-- 添加新元素到数组末尾
myArray[#myArray + 1] = 60-- 循环遍历数组
for i = 1, #myArray doprint(myArray[i])
end
二维数组:
-- 初始化数组 -- 三行三列
array = {}
for i=1,3 doarray[i] = {}for j=1,3 doarray[i][j] = i*jend
end-- 访问数组
for i=1,3 dofor j=1,3 doprint(array[i][j])end
end
迭代器与表 (重点)
Lua 迭代器 | 菜鸟教程
【Lua学习笔记】Lua进阶——Table,迭代器_lua迭代器-CSDN博客
Lua:06—table表类型:表索引、表构造器、数组、序列、table标准库
总结:
- ipairs 会略过数组非正数索引,以及其他字典索引,从数组的[1]索引开始迭代 (对应index=0),顺序迭代直到遇到 nil。因此 ipairs 通常只用于迭代数组。
- pairs 遇到 nil 会直接跳过,也可以遍历其他类型的索引,但迭代顺序是未定义的,因此 pairs 用于迭代除数组外的其他表类型。
- 合法索引 (符合命名规则的索引) 可以直接使用
a = {1, 2, t = 'a'}
这种方式定义,而非法索引 (负数索引以及不符合命名规则的索引) 需要使用[]
的方式定义,且字符串索引需要加引号,如a = {[-1] = 5, ['+'] = 'add'}
。
表部分操作:
-方法 | -方法描述 |
---|---|
table.concat (table [, sep [, start [, end]]]) | concat是concatenate(连锁, 连接)的缩写. table.concat()函数列出参数中指定table的数组部分从start位置到end位置的所有元素, 元素间以指定的分隔符(sep)隔开。 |
table.insert (table, [pos,] value) | 在table的数组部分指定位置(pos)插入值为value的一个元素. pos参数可选, 默认为数组部分末尾. |
table.remove (table [, pos]) | 返回table数组部分位于pos位置的元素. 其后的元素会被前移. pos参数可选, 默认为table长度, 即从最后一个元素删起。 |
table.sort (table [, comp]) | 对给定的table进行升序排序。 |
模块与包
Lua 的模块是由变量、函数等已知元素组成的 table,因此创建一个模块很简单,就是创建一个 table,然后把需要导出的常量、函数放入其中,最后返回这个 table 就行。
-- 文件名为 module.lua
-- 定义一个名为 module 的模块
module = {}-- 定义一个常量
module.constant = "这是一个常量"-- 定义一个函数
function module.func1()io.write("这是一个公有函数!\n")
endlocal function func2()print("这是一个私有函数!")
endfunction module.func3()func2()
endreturn module
加载模块:
require("<模块名>") or require "<模块名>" or local m = require("module")
加载完毕后直接使用就行 – 模块的定义与使用与 table 一样:
-- test_module.lua 文件
-- module 模块为上文提到到 module.lua
require("module")print(module.constant)module.func3()
需要注意的是,Lua 使用 package.path
和 package.cpath
来查找模块的位置。这两个变量分别用于查找 Lua 脚本模块(.lua
文件)和 C 库模块(.so
或 .dll
文件)。
因此,对于自定义模块,我们需要修改 package.path
来添加自定义的模块查找路径:
package.path = package.path .. ";~/lua/module.lua"local mymodule = require("mymodule") -- Lua 会在指定路径中查找模块