Skip to content

基本语法

变量定义

  • 变量在使用前,需要在代码中进行声明,即创建该变量。
  • 编译程序执行代码之前编译器需要知道如何给语句变量开辟存储区,用于存储变量的值。
  • 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
0true

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

函数

  • 函数是对语句和表达式进行抽象的主要方法。既可以用来处理一些特殊的工作,也可以用来计算一些值。
  • 函数主要有两种用途:
  1. 完成指定的任务,这种情况下函数作为调用语句使用;
  2. 计算并返回值,这种情况下函数作为赋值语句的表达式使用。

函数定义

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,逻辑非为 falsenot(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
\ddd1到3位八进制数所代表的任意字符三位八进制
\xhh1到2位十六进制所代表的任意字符二位十六进制

字符串操作

常用字符串操作

序号方法 & 用途
1string.upper(argument):
字符串全部转为大写字母。
2string.lower(argument):
字符串全部转为小写字母。
3string.sub(s, i [, j]):
s 为要截取的字符串,i 为截取开始位置,j 为截取结束位置,默认为 -1,最后一个字符。
4string.gsub(mainString,findString,replaceString,num)
在字符串中替换。
mainString 为要操作的字符串, findString 为被替换的字符,replaceString 要替换的字符,num 替换次数(可以忽略,则全部替换),如:
string.gsub("aaaa","a","z",3);
zzza    3
5string.find (str, substr, [init, [plain]])
在一个指定的目标字符串 str 中搜索指定的内容 substr,如果找到了一个匹配的子串,就会返回这个子串的起始索引和结束索引,不存在则返回 nil。
init 指定了搜索的起始位置,默认为 1,可以一个负数,表示从后往前数的字符个数。
plain 表示是否使用简单模式,默认为 false,true 只做简单的查找子串的操作,false 表示使用使用正则模式匹配。
以下实例查找字符串 "Lua" 的起始索引和结束索引位置:
string.find("Hello Lua user", "Lua", 1)
7 9
6string.reverse(arg)
字符串反转
string.reverse("Lua")
auL
7string.format(...)
返回一个类似printf的格式化字符串
string.format("the value is:%d",4)
the value is:4
8string.char(arg) 和 string.byte(arg[,int])
char 将整型数字转成字符并连接, byte 转换字符为整数值(可以指定某个字符,默认第一个字符)
string.char(97,98,99,100)
abcd
string.byte("ABCD",4)
68
string.byte("ABCD")
65
9string.len(arg)
计算字符串长度
string.len("abc")
3
10string.rep(string, n)
返回字符串string的n个拷贝
string.rep("abcd",2)
abcdabcd
11..
链接两个字符串
print("www.ai-v".."ision.com")
www.ai-vision.com
12string.gmatch(str, pattern)
返回一个迭代器函数,每一次调用这个函数,返回一个在字符串 str 找到的下一个符合 pattern 描述的子串。如果参数 pattern 描述的字符串没有找到,迭代函数返回nil
for word in string.gmatch("Hello ai vision", "%a+") do print(word) end
Hello
ai
vision
13string.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 - 接受一个字符串并按照给定的参数格式化该字符串

为进一步细化格式, 可以在%号后添加参数. 参数将以如下的顺序读入:

  1. 符号: 一个+号表示其后的数字转义符将让正数显示正号. 默认情况下只有负数显示符号.
  2. 占位符: 一个0, 在后面指定了字串宽度时占位用. 不填时的默认占位符是空格.
  3. 对齐标识: 在指定了字串宽度时, 默认为右对齐, 增加-号可以改为左对齐.
  4. 宽度数值
  5. 小数位数/字串裁切: 在宽度数值后增加的小数部分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

AI-Vision,让3D测量更简单