Appearance
基本语法
变量定义
- 变量在使用前,需要在代码中进行声明,即创建该变量。
- 编译程序执行代码之前编译器需要知道如何给语句变量开辟存储区,用于存储变量的值。
- Lua 变量有三种类型:全局变量、局部变量、表中的域。
- Lua 中的变量全是全局变量,哪怕是语句块或是函数里,除非用 local 显式声明为局部变量。
- 局部变量的作用域为从声明位置开始到所在语句块结束。
- 变量的默认值均为 nil。
lua
-- test.lua 文件脚本
a = 5 -- 全局变量
local b = 5 -- 局部变量
function joke()
c = 5 -- 全局变量
local d = 6 -- 局部变量
end
joke()
print(c,d) --> 5 nil
do
local a = 6 -- 局部变量
b = 6 -- 对局部变量重新赋值
print(a,b); --> 6 6
end
print(a,b) --> 5 6
输出结果为:
lua
5 nil
6 6
5 6
数据类型
- Lua是动态类型语言,变量不要类型定义,只需要为变量赋值。
- 值可以存储在变量中,作为参数传递或结果返回。
- Lua中有8个基本类型,AIV只使用其中5种,分别为:nil、boolean、number、stringfunction。
数据类型 | 描述 |
---|---|
nil | 只有值nil属于该类,表示一个无效值(在条件表达式中相当于false)。 |
boolean | 包含两个值:false和true。 |
number | 表示双精度类型的实浮点数 |
string | 字符串由一对双引号或单引号来表示 |
function | 由C或Lua编写的函数 |
lua
print(type("Hello world")) --> string
print(type(10.4*3)) --> number
print(type(print)) --> function
print(type(type)) --> function
print(type(true)) --> boolean
print(type(nil)) --> nil
print(type(type(X))) --> string
流程控制
- Lua 编程语言流程控制语句通过程序设定一个或多个条件语句来设定。在条件为 true 时执行指定程序代码,在条件为 false 时执行其他指定代码。
if语句
lua
--[ 0 为 true ]
if(0)
then
print("0 为 true")
end
输出结果为:
lua
0 为 true
if...else语句
lua
if(布尔表达式)
then
--[ 布尔表达式为 true 时执行该语句块 --]
else
--[ 布尔表达式为 false 时执行该语句块 --]
end
以下用于判断变量a的值:
lua
--[ 定义变量 --]
a = 100;
--[ 检查条件 --]
if( a < 20 )
then
--[ if 条件为 true 时执行该语句块 --]
print("a 小于 20" )
else
--[ if 条件为 false 时执行该语句块 --]
print("a 大于 20" )
end
print("a 的值为 :", a)
输出结果为:
lua
a 大于 20
a 的值为 : 100
if...elseif...else 语句
lua
if( 布尔表达式 1)
then
--[ 在布尔表达式 1 为 true 时执行该语句块 --]
elseif( 布尔表达式 2)
then
--[ 在布尔表达式 2 为 true 时执行该语句块 --]
elseif( 布尔表达式 3)
then
--[ 在布尔表达式 3 为 true 时执行该语句块 --]
else
--[ 如果以上布尔表达式都不为 true 则执行该语句块 --]
end
以下用于判断变量a的值:
lua
--[ 定义变量 --]
a = 100
--[ 检查布尔条件 --]
if( a == 10 )
then
--[ 如果条件为 true 打印以下信息 --]
print("a 的值为 10" )
elseif( a == 20 )
then
--[ if else if 条件为 true 时打印以下信息 --]
print("a 的值为 20" )
elseif( a == 30 )
then
--[ if else if condition 条件为 true 时打印以下信息 --]
print("a 的值为 30" )
else
--[ 以上条件语句没有一个为 true 时打印以下信息 --]
print("没有匹配 a 的值" )
end
print("a 的真实值为: ", a )
输出结果为:
lua
没有匹配 a 的值
a 的真实值为: 100
if嵌套
可以在一个if或elseif语句中插入其他的if或elseif语句。语法如下:
lua
if( 布尔表达式 1)
then
--[ 布尔表达式 1 为 true 时执行该语句块 --]
if(布尔表达式 2)
then
--[ 布尔表达式 2 为 true 时执行该语句块 --]
end
end
lua
--[ 定义变量 --]
a = 100;
b = 200;
--[ 检查条件 --]
if( a == 100 )
then
--[ if 条件为 true 时执行以下 if 条件判断 --]
if( b == 200 )
then
--[ if 条件为 true 时执行该语句块 --]
print("a 的值为 100 b 的值为 200" );
end
end
print("a 的值为 :", a );
print("b 的值为 :", b );
输出结果为:
lua
a 的值为 100 b 的值为 200
a 的值为 : 100
b 的值为 : 200
循环控制
for循环
- for循环语句可以重复执行指定语句,重复次数可在for语句中控制。
- for语句有两大类:数值for循环、泛型for循环
数值for循环
lua
for var=exp1,exp2,exp3 do
<执行体>
end
var 从 exp1 变化到 exp2,每次变化以 exp3 为步长递增 var,并执行一次 "执行体"。exp3 是可选的,如果不指定,默认为1。
lua
for i=1,f(x) do
print(i)
end
for i=10,1,-1 do
print(i)
end
for的三个表达式在循环开始前一次性求值,以后不再进行求值。比如上面的f(x)只会在循环开始前执行一次,其结果用在后面的循环中。举例如下:
lua
function f(x)
print("function")
return x*2
end
for i=1,f(5) do print(i)
end
输出结果为:
lua
function
1
2
3
4
5
6
7
8
9
10
泛型for循环
泛型for循环通过一个迭代器函数来遍历所有值,类似java中的foreach语句。
lua
--打印数组a的所有值
a = {"one", "two", "three"}
for i, v in ipairs(a) do
print(i, v)
end
i是数组索引值,v是对应索引的数组元素值。ipairs是Lua提供的一个迭代器函数,用来迭代数组。举例如下:
lua
#!/usr/local/bin/lua
days = {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"}
for i,v in ipairs(days) do print(v) end
输出结果为:
lua
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
while循环
- while 循环语句在判断条件为 true 时会重复执行循环体语句。语法为:
lua
while(condition)
do
statements
end
在condition(条件)为 false 时会跳过当前循环并开始脚本执行紧接着的语句。举例如下:
lua
a=10
while( a < 20 )
do
print("a 的值为:", a)
a = a+1
end
输出结果为:
lua
a 的值为: 10
a 的值为: 11
a 的值为: 12
a 的值为: 13
a 的值为: 14
a 的值为: 15
a 的值为: 16
a 的值为: 17
a 的值为: 18
a 的值为: 19
函数
- 函数是对语句和表达式进行抽象的主要方法。既可以用来处理一些特殊的工作,也可以用来计算一些值。
- 函数主要有两种用途:
- 完成指定的任务,这种情况下函数作为调用语句使用;
- 计算并返回值,这种情况下函数作为赋值语句的表达式使用。
函数定义
lua
optional_function_scope function function_name( argument1, argument2, argument3..., argumentn)
function_body
return result_params_comma_separated
end
- optional_function_scope: 该参数是可选的指定函数是全局函数还是局部函数,未设置该参数默认为全局函数,如果你需要设置函数为局部函数需要使用关键字 local。
- function_name: 指定函数名称。
- argument1, argument2, argument3..., argumentn: 函数参数,多个参数以逗号隔开,函数也可以不带参数。
- function_body: 函数体,函数中需要执行的代码语句块。
- result_params_comma_separated: 函数返回值,Lua语言函数可以返回多个值,每个值以逗号隔开。
lua
--[[ 函数返回两个值的最大值 --]]
function max(num1, num2)
if (num1 > num2) then
result = num1;
else
result = num2;
end
return result;
end
-- 调用函数
print("两值比较最大值为 ",max(10,4))
print("两值比较最大值为 ",max(5,6))
上面实例定义了函数 max(),参数为 num1, num2,用于比较两值的大小,并返回最大值,输出结果为:
lua
两值比较最大值为 10
两值比较最大值为 6
多返回值
- 函数可以返回多个结果值,比如string.find,其返回匹配串"开始和结束的下标"(如果不存在匹配串返回nil)
lua
function maximum (a)
local mi = 1 -- 最大值索引
local m = a[mi] -- 最大值
for i,val in ipairs(a) do
if val > m then
mi = i
m = val
end
end
return m, mi
end
print(maximum({8,10,23,12,5}))
上例表示,在return后列出要返回的值的列表即可返回多值,输出结果为:
lua
23 3
运算符
运算符是一个特殊的符号,用于告诉解释器执行特定的数学或逻辑运算。Lua提供了以下几种运算符类型:
- 算术运算符
- 关系运算符
- 逻辑运算符
- 其他运算符
算术运算符
设定 A 的值为10,B 的值为 20:
操作符 | 描述 | 实例 |
---|---|---|
+ | 加法 | A + B 输出结果 30 |
- | 减法 | A - B 输出结果 -10 |
* | 乘法 | A - B 输出结果 -10 |
/ | 除法 | B / A 输出结果 2 |
% | 取余 | B % A 输出结果 0 |
^ | 乘幂 | A^2 输出结果 100 |
- | 负号 | A^2 输出结果 100 |
// | 整除运算符 | 5//2 输出结果 2 |
关系运算符
设定 A 的值为10,B 的值为 20:
操作符 | 描述 | 实例 |
---|---|---|
== | 等于,检测两个值是否相等,相等返回 true,否则返回 false | (A == B) 为 false |
~= | 不等于,检测两个值是否相等,不相等返回 true,否则返回 false | (A ~= B) 为 true |
> | 大于,如果左边的值大于右边的值,返回 true,否则返回 false | (A > B) 为 false |
< | 大于,如果左边的值大于右边的值,返回 true,否则返回 false | (A < B) 为 true |
>= | 大于,如果左边的值大于右边的值,返回 true,否则返回 false | (A >= B) 返回 false |
<= | 大于,如果左边的值大于右边的值,返回 true,否则返回 false | (A >= B) 返回 false |
逻辑运算符
设定 A 的值为 true,B 的值为 false:
操作符 | 描述 | 实例 |
---|---|---|
and | 逻辑与操作符。 若 A 为 false,则返回 A,否则返回 B | (A and B) 为 false |
or | 逻辑或操作符。 若 A 为 true,则返回 A,否则返回 B | (A or B) 为 true |
not | 逻辑非操作符。与逻辑运算结果相反,如果条件为 true,逻辑非为 false | not(A and B) 为 true |
其他运算符
下表列出了连接运算符与计算表或字符串长度的运算符:
操作符 | 描述 | 实例 |
---|---|---|
.. | 连接两个字符串 | a..b ,其中 a 为 "Hello " , b 为 "AI-Vision", 输出结果为 "Hello AI-Vision" |
# | 获取字符串长度 | #"Hello" 返回 5 |
运算符优先级
从高到低的顺序:
lua
^
not - (unary)
* / %
+ -
..
< > <= >= ~= ==
and
or
除了 ^ 和 .. 外所有的二元运算符都是左连接的。
lua
a+i < b/2+1 <--> (a+i) < ((b/2)+1)
5+x^2*8 <--> 5+((x^2)*8)
a < y and y <= z <--> (a < y) and (y <= z)
-x^2 <--> -(x^2)
x^y^z <--> x^(y^z)
举例如下:
lua
a = 20
b = 10
c = 15
d = 5
e = (a + b) * c / d;-- ( 30 * 15 ) / 5
print("(a + b) * c / d 运算值为 :",e )
e = ((a + b) * c) / d; -- (30 * 15 ) / 5
print("((a + b) * c) / d 运算值为 :",e )
e = (a + b) * (c / d);-- (30) * (15/5)
print("(a + b) * (c / d) 运算值为 :",e )
e = a + (b * c) / d; -- 20 + (150/5)
print("a + (b * c) / d 运算值为 :",e )
输出结果为:
lua
(a + b) * c / d 运算值为 : 90.0
((a + b) * c) / d 运算值为 : 90.0
(a + b) * (c / d) 运算值为 : 90.0
a + (b * c) / d 运算值为 : 50.0
字符串
字符串或串(String)是由数字、字母、下划线组成的一串字符。
字符串是一种基本的数据类型,用于存储文本数据。
字符串可以包含任意字符,包括字母、数字、符号、空格以及其他特殊字符。
符串可以使用以下三种方式来表示:
- 单引号间的一串字符
lua
local str1 = 'This is a string.'
local str2 = "This is also a string."
- 双引号间的一串字符
lua
local str = "Hello, "
str = str .. "World!" -- 创建一个新的字符串并将其赋值给str
print(str) -- 输出 "Hello, World!"
- [[ 与 ]] 间的一串字符
lua
local multilineString = [[
This is a multiline string.
It can contain multiple lines of text.
No need for escape characters.
]]
print(multilineString)
以上三种方式的字符串举例如下:
lua
string1 = "Hello"
print("\"字符串 1 是\"",string1)
string2 = 'AI-Vision'
print("字符串 2 是",string2)
string3 = [["Hello AI-Vision"]]
print("字符串 3 是",string3)
输出结果为:
lua
"字符串 1 是" Hello
字符串 2 是 AI-Vision
字符串 3 是 "Hello AI-Vision"
字符串长度计算
要计算字符串的长度(即字符串中字符的个数),可以使用 string.len函数或 utf8.len 函数,包含中文的一般用 utf8.len,string.len 函数用于计算只包含 ASCII 字符串的长度。举例如下:
lua
local myString = "Hello, 世界!"
-- 计算字符串的长度(字符个数)
local length1 = utf8.len(myString)
print(length1) -- 输出 9
-- string.len 函数会导致结果不准确
local length2 = string.len(myString)
print(length2) -- 输出 14
转义字符
转义字符用于表示不能直接显示的字符,比如后退键,回车键等,如在字符串转换双引号可以使用 \。
所有的转义字符和所对应的意义:
转义字符 | 意义 | ASCII码值(十进制) |
---|---|---|
\a | 响铃(BEL) | 007 |
\b | 退格(BS) ,将当前位置移到前一列 | 008 |
\f | 换页(FF),将当前位置移到下页开头 | 012 |
\n | 换行(LF) ,将当前位置移到下一行开头 | 010 |
\r | 回车(CR) ,将当前位置移到本行开头 | 013 |
\t | 水平制表(HT) (跳到下一个TAB位置) | 009 |
\v | 垂直制表(VT) | 011 |
\ | 代表一个反斜线字符''' | 092 |
' | 代表一个单引号(撇号)字符 | 039 |
" | 代表一个双引号字符 | 034 |
\0 | 空字符(NULL) | 000 |
\ddd | 1到3位八进制数所代表的任意字符 | 三位八进制 |
\xhh | 1到2位十六进制所代表的任意字符 | 二位十六进制 |
字符串操作
常用字符串操作
序号 | 方法 & 用途 |
---|---|
1 | string.upper(argument): 字符串全部转为大写字母。 |
2 | string.lower(argument): 字符串全部转为小写字母。 |
3 | string.sub(s, i [, j]): s 为要截取的字符串,i 为截取开始位置,j 为截取结束位置,默认为 -1,最后一个字符。 |
4 | string.gsub(mainString,findString,replaceString,num) 在字符串中替换。 mainString 为要操作的字符串, findString 为被替换的字符,replaceString 要替换的字符,num 替换次数(可以忽略,则全部替换),如: string.gsub("aaaa","a","z",3); zzza 3 |
5 | string.find (str, substr, [init, [plain]]) 在一个指定的目标字符串 str 中搜索指定的内容 substr,如果找到了一个匹配的子串,就会返回这个子串的起始索引和结束索引,不存在则返回 nil。 init 指定了搜索的起始位置,默认为 1,可以一个负数,表示从后往前数的字符个数。 plain 表示是否使用简单模式,默认为 false,true 只做简单的查找子串的操作,false 表示使用使用正则模式匹配。 以下实例查找字符串 "Lua" 的起始索引和结束索引位置: string.find("Hello Lua user", "Lua", 1) 7 9 |
6 | string.reverse(arg) 字符串反转 string.reverse("Lua") auL |
7 | string.format(...) 返回一个类似printf的格式化字符串 string.format("the value is:%d",4) the value is:4 |
8 | string.char(arg) 和 string.byte(arg[,int]) char 将整型数字转成字符并连接, byte 转换字符为整数值(可以指定某个字符,默认第一个字符) string.char(97,98,99,100) abcd string.byte("ABCD",4) 68 string.byte("ABCD") 65 |
9 | string.len(arg) 计算字符串长度 string.len("abc") 3 |
10 | string.rep(string, n) 返回字符串string的n个拷贝 string.rep("abcd",2) abcdabcd |
11 | .. 链接两个字符串 print("www.ai-v".."ision.com") www.ai-vision.com |
12 | string.gmatch(str, pattern) 返回一个迭代器函数,每一次调用这个函数,返回一个在字符串 str 找到的下一个符合 pattern 描述的子串。如果参数 pattern 描述的字符串没有找到,迭代函数返回nil for word in string.gmatch("Hello ai vision", "%a+") do print(word) end Hello ai vision |
13 | string.match(str, pattern, init) string.match()只寻找源字串str中的第一个配对. 参数init可选, 指定搜寻过程的起点, 默认为1。 在成功配对时, 函数将返回配对表达式中的所有捕获结果; 如果没有设置捕获标记, 则返回整个配对字符串. 当没有成功的配对时, 返回nil string.match("I have 2 questions for you.", "%d+ %a+") 2 questions string.format("%d, %q", string.match("I have 2 questions for you.", "(%d+) (%a+)")) 2, "questions" |
字符串格式化
string.format() 函数来生成具有特定格式的字符串, 函数的第一个参数是格式 , 之后是对应格式中每个代号的各种数据。
由于格式字符串的存在, 使得产生的长字符串可读性大大提高了。这个函数的格式很像 C 语言中的 printf()。
以下实例演示了如何对字符串进行格式化操作:
格式字符串可能包含以下的转义码:
- %c - 接受一个数字, 并将其转化为ASCII码表中对应的字符
- %d, %i - 接受一个数字并将其转化为有符号的整数格式
- %o - 接受一个数字并将其转化为八进制数格式
- %u - 接受一个数字并将其转化为无符号整数格式
- %x - 接受一个数字并将其转化为十六进制数格式, 使用小写字母
- %X - 接受一个数字并将其转化为十六进制数格式, 使用大写字母
- %e - 接受一个数字并将其转化为科学记数法格式, 使用小写字母e
- %E - 接受一个数字并将其转化为科学记数法格式, 使用大写字母E
- %f - 接受一个数字并将其转化为浮点数格式
- %g(%G) - 接受一个数字并将其转化为%e(%E, 对应%G)及%f中较短的一种格式
- %q - 接受一个字符串并将其转化为可安全被Lua编译器读入的格式
- %s - 接受一个字符串并按照给定的参数格式化该字符串
为进一步细化格式, 可以在%号后添加参数. 参数将以如下的顺序读入:
- 符号: 一个+号表示其后的数字转义符将让正数显示正号. 默认情况下只有负数显示符号.
- 占位符: 一个0, 在后面指定了字串宽度时占位用. 不填时的默认占位符是空格.
- 对齐标识: 在指定了字串宽度时, 默认为右对齐, 增加-号可以改为左对齐.
- 宽度数值
- 小数位数/字串裁切: 在宽度数值后增加的小数部分n, 若后接f(浮点数转义符, 如%6.3f)则设定该浮点数的小数只保留n位, 若后接s(字符串转义符, 如%5.3s)则设定该字符串只显示前n位.
lua
string1 = "Hello"
string2 = "Ai-Vision"
number1 = 10
number2 = 20
-- 基本字符串格式化
print(string.format("基本格式化 %s %s",string1,string2))
-- 日期格式化
date = 2; month = 1; year = 2023
print(string.format("日期格式化 %02d/%02d/%03d", date, month, year))
-- 十进制格式化
print(string.format("%.4f",1/3))
输出结果为:
lua
基本格式化 Hello Ai-Vision
日期格式化 02/01/2023
0.3333
其他例子:
lua
string.format("%c", 83) -- 输出S
string.format("%+d", 17.0) -- 输出+17
string.format("%05d", 17) -- 输出00017
string.format("%o", 17) -- 输出21
string.format("%u", 3.14) -- 输出3
string.format("%x", 13) -- 输出d
string.format("%X", 13) -- 输出D
string.format("%e", 1000) -- 输出1.000000e+03
string.format("%E", 1000) -- 输出1.000000E+03
string.format("%6.3f", 13) -- 输出13.000
string.format("%q", "One\nTwo") -- 输出"One\
-- Two"
string.format("%s", "monkey") -- 输出monkey
string.format("%10s", "monkey") -- 输出 monkey
string.format("%5.3s", "monkey") -- 输出 mon
字符串截取
lua
-- 字符串
local sourcestr = "prefix--abcdefgh--suffix"
print("\n原始字符串", string.format("%q", sourcestr))
-- 截取部分,第4个到第15个
local first_sub = string.sub(sourcestr, 4, 15)
print("\n第一次截取", string.format("%q", first_sub))
-- 取字符串前缀,第1个到第8个
local second_sub = string.sub(sourcestr, 1, 8)
print("\n第二次截取", string.format("%q", second_sub))
-- 截取最后10个
local third_sub = string.sub(sourcestr, -10)
print("\n第三次截取", string.format("%q", third_sub))
-- 索引越界,输出原始字符串
local fourth_sub = string.sub(sourcestr, -100)
print("\n第四次截取", string.format("%q", fourth_sub))
输出结果为:
lua
原始字符串 "prefix--abcdefgh--suffix"
第一次截取 "fix--abcdefg"
第二次截取 "prefix--"
第三次截取 "gh--suffix"
第四次截取 "prefix--abcdefgh--suffix"
数组
数组,就是相同数据类型的元素按一定顺序排列的集合,可以是一维数组和多维数组。
在 Lua 中,数组不是一种特定的数据类型,而是一种用来存储一组值的数据结构。
实际上,Lua 中并没有专门的数组类型,而是使用一种被称为 "table" 的数据结构来实现数组的功能。
一维数组
一维数组是最简单的数组,其逻辑结构是线性表。
使用索引访问数组元素
lua
-- 创建一个数组
local myArray = {10, 20, 30, 40, 50}
-- 访问数组元素
print(myArray[1]) -- 输出 10
print(myArray[3]) -- 输出 30
要计算数组的长度(即数组中元素的个数),可以使用 # 操作符:
lua
local myArray = {10, 20, 30, 40, 50}
-- 计算数组长度
local length = #myArray
print(length) -- 输出 5
一维数组可以用 for 循环出数组中的元素,如下实例:
lua
-- 创建一个数组
local myArray = {10, 20, 30, 40, 50}
-- 循环遍历数组
for i = 1, #myArray do
print(myArray[i])
end
输出结果为:
lua
10
20
30
40
50