文章目录

  • 1、8种基本数据类型
  • nil(空)
  • boolean(布尔)
  • number(数字)
  • string(字符串)
  • table(表)
  • function(函数)
  • thread(线程)
  • userdata(自定义类型)
  • 2、Lua 变量
  • 赋值语句
  • 索引
  • 3、Lua 循环
  • while 循环
  • for 循环
  • repeat...until 循环
  • 循环嵌套
  • 循环控制语句
  • 4、流程控制
  • 5、函数
  • 6、运算符
  • 算术运算符
  • 关系运算符
  • 逻辑运算符
  • 其他运算符
  • 运算符优先级


1、8种基本数据类型

数据类型	描述
nil	这个最简单,只有值nil属于该类,表示一个无效值(在条件表达式中相当于false)。
boolean	包含两个值:false和true。
number	表示双精度类型的实浮点数
string	字符串由一对双引号或单引号来表示
function	由 C 或 Lua 编写的函数
userdata	表示任意存储在变量中的C数据结构
thread	表示执行的独立线路,用于执行协同程序
table	Lua 中的表(table)其实是一个"关联数组"(associative arrays),数组的索引可以是数字、字符串或表类型。在 Lua 里,table 的创建是通过"构造表达式"来完成,最简单构造表达式是{},用来创建一个空表。

我们可以使用 type 函数测试给定变量或者值的类型:
实例
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

nil(空)

nil 类型表示一种没有任何有效值,它只有一个值 -- nil,例如打印一个没有赋值的变量,便会输出一个 nil 值:

> print(type(a))
nil
>

对于全局变量和 table,nil 还有一个"删除"作用,给全局变量或者 table 表里的变量赋一个 nil 值,等同于把它们删掉,执行下面代码就知:
tab1 = { key1 = "val1", key2 = "val2", "val3" }
for k, v in pairs(tab1) do
    print(k .. " - " .. v)
end
 
tab1.key1 = nil
for k, v in pairs(tab1) do
    print(k .. " - " .. v)
end
nil 作比较时应该加上双引号 ":
> type(X)
nil
> type(X)==nil
false
> type(X)=="nil"
true
>

type(X)==nil 结果为 false 的原因是 type(X) 实质是返回的 "nil" 字符串,是一个 string 类型:

type(type(X))==string

boolean(布尔)

boolean 类型只有两个可选值:true(真) 和 false(假),Lua 把 false 和 nil 看作是 false,其他的都为 true,数字 0 也是 true:
实例
print(type(true))
print(type(false))
print(type(nil))
 
if false or nil then
    print("至少有一个是 true")
else
    print("false 和 nil 都为 false")
end

if 0 then
    print("数字 0 是 true")
else
    print("数字 0 为 false")
end

以上代码执行结果如下:

$ lua test.lua 
boolean
boolean
nil
false 和 nil 都为 false
数字 0 是 true

number(数字)

Lua 默认只有一种 number 类型 -- double(双精度)类型(默认类型可以修改 luaconf.h 里的定义),以下几种写法都被看作是 number 类型:
实例
print(type(2))
print(type(2.2))
print(type(0.2))
print(type(2e+1))
print(type(0.2e-1))
print(type(7.8263692594256e-06))

以上代码执行结果:

number
number
number
number
number
number

string(字符串)

字符串由一对双引号或单引号来表示。

string1 = "this is string1"
string2 = 'this is string2'

也可以用 2 个方括号 "[[]]" 来表示"一块"字符串。
实例
html = [[
<html>
<head></head>
<body>
    <a href="https://www.runoob.com/">菜鸟教程</a>
</body>
</html>
]]
print(html)

以下代码执行结果为:

<html>
<head></head>
<body>
    <a href="http://www.runoob.com/">菜鸟教程</a>
</body>
</html>

在对一个数字字符串上进行算术操作时,Lua 会尝试将这个数字字符串转成一个数字:
> print("2" + 6)
8.0
> print("2" + "6")
8.0
> print("2 + 6")
2 + 6
> print("-2e2" * "6")
-1200.0
> print("error" + 1)
stdin:1: attempt to perform arithmetic on a string value
stack traceback:
        stdin:1: in main chunk
        [C]: in ?
>

以上代码中"error" + 1执行报错了,字符串连接使用的是 .. ,如:

> print("a" .. 'b')
ab
> print(157 .. 428)
157428
> 

使用 # 来计算字符串的长度,放在字符串前面,如下实例:
实例
> len = "www.runoob.com"
> print(#len)
14
> print(#"www.runoob.com")
14
>

table(表)

在 Lua 里,table 的创建是通过"构造表达式"来完成,最简单构造表达式是{},用来创建一个空表。也可以在表里添加一些数据,直接初始化表:
实例
-- 创建一个空的 table
local tbl1 = {}
 
-- 直接初始表
local tbl2 = {"apple", "pear", "orange", "grape"}

Lua 中的表(table)其实是一个"关联数组"(associative arrays),数组的索引可以是数字或者是字符串。
实例
-- table_test.lua 脚本文件
a = {}
a["key"] = "value"
key = 10
a[key] = 22
a[key] = a[key] + 11
for k, v in pairs(a) do
    print(k .. " : " .. v)
end

脚本执行结果为:

$ lua table_test.lua 
key : value
10 : 33

不同于其他语言的数组把 0 作为数组的初始索引,在 Lua 里表的默认初始索引一般以 1 开始。
实例
-- table_test2.lua 脚本文件
local tbl = {"apple", "pear", "orange", "grape"}
for key, val in pairs(tbl) do
    print("Key", key)
end

脚本执行结果为:

$ lua table_test2.lua 
Key	1
Key	2
Key	3
Key	4

table 不会固定长度大小,有新数据添加时 table 长度会自动增长,没初始的 table 都是 nil。
实例
-- table_test3.lua 脚本文件
a3 = {}
for i = 1, 10 do
    a3[i] = i
end
a3["key"] = "val"
print(a3["key"])
print(a3["none"])

脚本执行结果为:

$ lua table_test3.lua 
val
nil

function(函数)

在 Lua 中,函数是被看作是"第一类值(First-Class Value)",函数可以存在变量里:
实例
-- function_test.lua 脚本文件
function factorial1(n)
    if n == 0 then
        return 1
    else
        return n * factorial1(n - 1)
    end
end
print(factorial1(5))
factorial2 = factorial1
print(factorial2(5))

脚本执行结果为:

$ lua function_test.lua 
120
120

function 可以以匿名函数(anonymous function)的方式通过参数传递:
实例
-- function_test2.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 function_test2.lua 
key1 = val1
key2 = val2

thread(线程)

在 Lua 里,最主要的线程是协同程序(coroutine)。它跟线程(thread)差不多,拥有自己独立的栈、局部变量和指令指针,可以跟其他协同程序共享全局变量和其他大部分东西。

线程跟协程的区别:线程可以同时多个运行,而协程任意时刻只能运行一个,并且处于运行状态的协程只有被挂起(suspend)时才会暂停。

userdata(自定义类型)

userdata 是一种用户自定义数据,用于表示一种由应用程序或 C/C++ 语言库所创建的类型,可以将任意 C/C++ 的任意数据类型的数据(通常是 struct 和 指针)存储到 Lua 变量中调用。

2、Lua 变量

##三种类型
变量在使用前,需要在代码中进行声明,即创建该变量。

编译程序执行代码之前编译器需要知道如何给语句变量开辟存储区,用于存储变量的值。

Lua 变量有三种类型:全局变量、局部变量、表中的域。

Lua 中的变量全是全局变量,哪怕是语句块或是函数里,除非用 local 显式声明为局部变量。

局部变量的作用域为从声明位置开始到所在语句块结束。

变量的默认值均为 nil。

-- 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 test.lua 
5	nil
6	6
5	6

赋值语句

赋值是改变一个变量的值和改变表域的最基本的方法。

a = "hello" .. "world"
t.n = t.n + 1

Lua 可以对多个变量同时赋值,变量列表和值列表的各个元素用逗号分开,赋值语句右边的值会依次赋给左边的变量。

a, b = 10, 2*x       <-->       a=10; b=2*x

遇到赋值语句Lua会先计算右边所有的值然后再执行赋值操作,所以我们可以这样进行交换变量的值:

x, y = y, x                     -- swap 'x' for 'y'
a[i], a[j] = a[j], a[i]         -- swap 'a[i]' for 'a[j]'

当变量个数和值的个数不一致时,Lua会一直以变量个数为基础采取以下策略:

a. 变量个数 > 值的个数             按变量个数补足nil
b. 变量个数 < 值的个数             多余的值会被忽略

实例
a, b, c = 0, 1
print(a,b,c)             --> 0   1   nil
 
a, b = a+1, b+1, b+2     -- value of b+2 is ignored
print(a,b)               --> 1   2
 
a, b, c = 0
print(a,b,c)             --> 0   nil   nil

上面最后一个例子是一个常见的错误情况,注意:如果要对多个变量赋值必须依次对每个变量赋值。

a, b, c = 0, 0, 0
print(a,b,c)             --> 0   0   0

多值赋值经常用来交换变量,或将函数调用返回给变量:

a, b = f()

f()返回两个值,第一个赋给a,第二个赋给b。

应该尽可能的使用局部变量,有两个好处:

    1. 避免命名冲突。
    2. 访问局部变量的速度比全局变量更快。

索引

对 table 的索引使用方括号 []。Lua 也提供了 . 操作。

t[i]
t.i                 -- 当索引为字符串类型时的一种简化写法
gettable_event(t,i) -- 采用索引访问本质上是一个类似这样的函数调用

实例
> site = {}
> site["key"] = "www.runoob.com"
> print(site["key"])
www.runoob.com
> print(site.key)
www.runoob.com

3、Lua 循环

while 循环

循环语法:

while(condition)
do
   statements
end
以下实例循环输出 a 的值:
实例
a=10
while( a < 20 )
do
   print("a 的值为:", a)
   a = a+1
end

执行以上代码,输出结果如下:

a 的值为:	10
a 的值为:	11
a 的值为:	12
a 的值为:	13
a 的值为:	14
a 的值为:	15
a 的值为:	16
a 的值为:	17
a 的值为:	18
a 的值为:	19

for 循环

Lua 编程语言中 for语句有两大类::

数值for循环
泛型for循环

数值for循环

Lua 编程语言中数值 for 循环语法格式:

for var=exp1,exp2,exp3 do  
    <执行体>  
end

var 从 exp1 变化到 exp2,每次变化以 exp3 为步长递增 var,并执行一次 “执行体”。exp3 是可选的,如果不指定,默认为1。

实例
for i=1,f(x) do
    print(i)
end
 
for i=10,1,-1 do
    print(i)
end

for的三个表达式在循环开始前一次性求值,以后不再进行求值。比如上面的f(x)只会在循环开始前执行一次,其结果用在后面的循环中。

验证如下:
实例
#!/usr/local/bin/lua  
function f(x)  
    print("function")  
    return x*2  
end  
for i=1,f(5) do print(i)  
end

以上实例输出结果为:

function
1
2
3
4
5
6
7
8
9
10

可以看到 函数f(x)只在循环开始前执行一次。

泛型for循环

泛型 for 循环通过一个迭代器函数来遍历所有值,类似 java 中的 foreach 语句。

Lua 编程语言中泛型 for 循环语法格式:

--打印数组a的所有值  
a = {"one", "two", "three"}
for i, v in ipairs(a) do
	print(i, v)
end 

i是数组索引值,v是对应索引的数组元素值。ipairs是Lua提供的一个迭代器函数,用来迭代数组。


实例
#!/usr/local/bin/lua  
days = {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"}  
for i,v in ipairs(days) do  print(v) end  

以上实例输出结果为:

Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday

repeat…until 循环

Lua 编程语言中 repeat…until 循环语法格式:

repeat
   statements
until( condition )

我们注意到循环条件判断语句(condition)在循环体末尾部分,所以在条件进行判断前循环体都会执行一次。
如果条件判断语句(condition)为 false,循环会重新开始执行,直到条件判断语句(condition)为 true 才会停止执行。

实例
--[ 变量定义 --]
a = 10
--[ 执行循环 --]
repeat
   print("a的值为:", a)
   a = a + 1
until( a > 15 )

执行以上代码,程序输出结果为:

a的值为:	10
a的值为:	11
a的值为:	12
a的值为:	13
a的值为:	14
a的值为:	15

循环嵌套

语法

Lua 编程语言中 for 循环嵌套语法格式:

for init,max/min value, increment
do
   for init,max/min value, increment
   do
      statements
   end
   statements
end

Lua 编程语言中 while 循环嵌套语法格式:

while(condition)
do
   while(condition)
   do
      statements
   end
   statements
end

Lua 编程语言中 repeat…until 循环嵌套语法格式:

repeat
   statements
   repeat
      statements
   until( condition )
until( condition )

除了以上同类型循环嵌套外,我们还可以使用不同的循环类型来嵌套,如 for 循环体中嵌套 while 循环。

实例
j =2
for i=2,10 do
   for j=2,(i/j) , 2 do
      if(not(i%j))
      then
         break
      end
      if(j > (i/j))then
         print("i 的值为:",i)
      end
   end
end

以上代码执行结果为:

i 的值为:	8
i 的值为:	9
i 的值为:	10

循环控制语句

break 语句

break 语句	退出当前循环或语句,并开始脚本执行紧接着的语句。

goto 语句
Lua 语言中的 goto 语句允许将控制流程无条件地转到被标记的语句处。
语法格式如下所示:

goto Label

Label 的格式为:

:: Label ::
实例 1
local a = 1
::label:: print("--- goto label ---")

a = a+1
if a < 3 then
    goto label   -- a 小于 3 的时候跳转到标签 label
end

输出结果为:

--- goto label ---
--- goto label ---

从输出结果可以看出,多输出了一次 --- goto label ---。
实例 2
i = 0
::s1:: do
  print(i)
  i = i+1
end
if i>3 then
  os.exit()   -- i 大于 3 时退出
end
goto s1

输出结果为:

0
1
2
3
有了 goto,我们可以实现 continue 的功能:
实例 3
for i=1, 3 do
    if i <= 2 then
        print(i, "yes continue")
        goto continue
    end
    print(i, " no continue")
    ::continue::
    print([[i'm end]])
end

输出结果为:

1   yes continue
i'm end
2   yes continue
i'm end
3    no continue
i'm end

4、流程控制

控制结构的条件表达式结果可以是任何值,Lua认为false和nil为假,true和非nil为真。
if 语句 if 语句 由一个布尔表达式作为条件判断,其后紧跟其他语句组成。

实例
--[ 0 为 true ]
if(0)
then
    print("0 为 true")
end

以上代码输出结果为:

0 为 true

if…else 语句 if 语句 可以与 else 语句搭配使用, 在 if 条件表达式为 false 时执行 else 语句代码。

if(布尔表达式)
then
   --[ 布尔表达式为 true 时执行该语句块 --]
else
   --[ 布尔表达式为 false 时执行该语句块 --]
end

if 嵌套语句 你可以在if 或 else if中使用一个或多个 if 或 else if 语句 。

if( 布尔表达式 1)
then
   --[ 布尔表达式 1 为 true 时执行该语句块 --]
   if(布尔表达式 2)
   then
      --[ 布尔表达式 2 为 true 时执行该语句块 --]
   end
end

5、函数

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语言函数可以返回多个值,每个值以逗号隔开。

以下实例定义了函数 max(),参数为 num1, num2,用于比较两值的大小,并返回最大值:

--[[ 函数返回两个值的最大值 --]]
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))

以上代码执行结果为:

两值比较最大值为 	10
两值比较最大值为 	6

Lua 中我们可以将函数作为参数传递给函数,如下实例:

myprint = function(param)
   print("这是打印函数 -   ##",param,"##")
end

function add(num1,num2,functionPrint)
   result = num1 + num2
   -- 调用传递的函数参数
   functionPrint(result)
end
myprint(10)
-- myprint 函数作为参数传递
add(2,5,myprint)

以上代码执行结果为:

这是打印函数 -   ##	10	##
这是打印函数 -   ##	7	##

多返回值
Lua函数可以返回多个结果值,比如string.find,其返回匹配串"开始和结束的下标"(如果不存在匹配串返回nil)。

> s, e = string.find("www.runoob.com", "runoob") 
> print(s, e)
5	10

Lua函数中,在return后列出要返回的值的列表即可返回多值,如:

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}))

以上代码执行结果为:

23	3

可变参数
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

我们可以将可变参数赋值给一个变量。例如,我们计算几个数的平均值:

function average(...)
   result = 0
   local arg={...}    --> arg 为一个表,局部变量
   for i,v in ipairs(arg) do
      result = result + v
   end
   print("总共传入 " .. #arg .. " 个数")
   return result/#arg
end

print("平均值为",average(10,5,3,4,5,6))

以上代码执行结果为:

总共传入 6 个数
平均值为	5.5

我们也可以通过 select(“#”,…) 来获取可变参数的数量:

function average(...)
   result = 0
   local arg={...}
   for i,v in ipairs(arg) do
      result = result + v
   end
   print("总共传入 " .. select("#",...) .. " 个数")
   return result/select("#",...)
end

print("平均值为",average(10,5,3,4,5,6))

以上代码执行结果为:

总共传入 6 个数
平均值为	5.5

有时候我们可能需要几个固定参数加上可变参数,固定参数必须放在变长参数之前:

function fwrite(fmt, ...)  ---> 固定的参数fmt
    return io.write(string.format(fmt, ...))    
end

fwrite("runoob\n")       --->fmt = "runoob", 没有变长参数。  
fwrite("%d%d\n", 1, 2)   --->fmt = "%d%d", 变长参数为 1 和 2

输出结果为:

runoob
12

通常在遍历变长参数的时候只需要使用 {…},然而变长参数可能会包含一些 nil,那么就可以用 select 函数来访问变长参数了:select(‘#’, …) 或者 select(n, …)

select('#', …) 返回可变参数的长度。
select(n, …) 用于返回从起点 n 开始到结束位置的所有参数列表。

调用 select 时,必须传入一个固定实参 selector(选择开关) 和一系列变长参数。如果 selector 为数字 n,那么 select 返回参数列表中从索引 n 开始到结束位置的所有参数列表,否则只能为字符串 #,这样 select 返回变长参数的总数。

function f(...)
    a = select(3,...)  -->从第三个位置开始,变量 a 对应右边变量列表的第一个参数
    print (a)
    print (select(3,...)) -->打印所有列表参数
end

f(0,1,2,3,4,5)

输出结果为:

2
2       3       4       5

实例
do  
    function foo(...)  
        for i = 1, select('#', ...) do  -->获取参数总数
            local arg = select(i, ...); -->读取参数,arg 对应的是右边变量列表的第一个参数
            print("arg", arg);  
        end  
    end  
 
    foo(1, 2, 3, 4);  
end

输出结果为:

arg	1
arg	2
arg	3
arg	4

6、运算符

算术运算符
关系运算符
逻辑运算符
其他运算符

算术运算符

下表列出了 Lua 语言中的常用算术运算符,设定 A 的值为10,B 的值为 20:

操作符	描述	         实例
+	    加法	        A + B 输出结果 30
-	    减法	        A - B 输出结果 -10
*	    乘法	        A * B 输出结果 200
/	    除法	        B / A 输出结果 2
%	    取余	        B % A 输出结果 0
^	    乘幂	        A^2 输出结果 100
-	    负号	        -A 输出结果 -10
//  整除运算符(>=lua5.3)	5//2 输出结果 2

在 lua 中,/ 用作除法运算,计算结果包含小数部分,// 用作整除运算,计算结果不包含小数部分:

关系运算符

下表列出了 Lua 语言中的常用关系运算符,设定 A 的值为10,B 的值为 20:

操作符	描述	实例
==	等于,检测两个值是否相等,相等返回 true,否则返回 false	(A == B) 为 false。
~=	不等于,检测两个值是否相等,不相等返回 true,否则返回 false	(A ~= B) 为 true。
>	大于,如果左边的值大于右边的值,返回 true,否则返回 false	(A > B) 为 false。
<	小于,如果左边的值大于右边的值,返回 false,否则返回 true	(A < B) 为 true。
>=	大于等于,如果左边的值大于等于右边的值,返回 true,否则返回 false	(A >= B) 返回 false。
<=	小于等于, 如果左边的值小于等于右边的值,返回 true,否则返回 false	(A <= B) 返回 true。

逻辑运算符

下表列出了 Lua 语言中的常用逻辑运算符,设定 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。

其他运算符

下表列出了 Lua 语言中的连接运算符与计算表或字符串长度的运算符:

操作符	描述	实例
..	连接两个字符串	a..b ,其中 a 为 "Hello " , b 为 "World", 输出结果为 "Hello World"。
#	一元运算符,返回字符串或表的长度。	#"Hello" 返回 5

运算符优先级

从高到低的顺序:

^
not    - (unary)
*      /       %
+      -
..
<      >      <=     >=     ~=     ==
and
or

除了 ^ 和 … 外所有的二元运算符都是左连接的。

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)

后续看情况更新
回到顶部