Lua语言

1、Lua简介

1.1 Lua是什么?

​ Lua是一个小巧的脚本语言。其设计目的是为了通过灵活嵌入应用程序中从而为应用程序提供灵活的扩展和定制功能。Lua是标准C语言编写,几乎在所有操作系统和平台上都可以编译运行。

​ Lua没有提供强大的库,这是由它的定位决定的。所以Lua不适合作为独立应用程序开发语言。

​ 简单来说Lua是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放,其设计目的是为了嵌入应用程序中,从而为应用提供灵活的扩展和定制功能。

1.2 Lua语言特性

  • 它用标准 C 语言编写并以源代码形式开放,编译后仅仅 100多K,可以很方便的嵌入别的程序里。
  • Lua 提供了非常易于使用的扩展接口和机制:由宿主语言(通常是 C 或 C++ )提供这些功能,Lua 可以使用它们,就像是本来就内置的功能一样。
  • 支持面向过程编程 和 函数式编程。
  • 自动内存管理,只提供了一种通用类型的表(table),用它可以实现数组,哈希表,集合,对象。
  • 语言内置模式匹配,闭包(closure),函数也可以看做一个值,提供多线程(协同进程,并非操作系统所支持的线程)支持。
  • 通过闭包和 table 可以很方便地支持面向对象编程所需要的一些关键机制,比如数据抽象,虚函数,继承和重载等。

1.3 Lua安装

参考文档:https://blog.csdn.net/xiaowu714/article/details/127763087

2、Lua基本语法

​ Lua有交互式编程和脚本式编程。交互式编程就是直接输入语法,就能执行。脚本式编程需要编写脚本,然后再执行命令 执行脚本才可以。

2.1 交互式编程

​ Lua 提供了交互式编程模式。我们可以在命令行中输入程序并立即查看效果。Lua 交互式编程模式可以通过命令 lua -i 或 lua 来启用:

Last login: Tue Nov  8 10:04:57 2022 from 10.1.25.163
[root@bogon ~]# lua -i
Lua 5.4.1  Copyright (C) 1994-2020 Lua.org, PUC-Rio
//在命令行中,输入以下命令,输出结果如下:
> print("Hello word")
Hello word
>

2.2 脚本式编程

​ 我们可以将 Lua 程序代码保存到一个以lua结尾的文件,并执行;该模式称为脚本式编程,如我们将如下代码存储在名为 hello.lua 的脚本文件中:

print("hello world!")
print("xiaowu first Lua")

​ 使用 lua hello.lua命令执行以上脚本,输出结果为:

[root@bogon lua-5.4.1]# lua hello.lua
hello world!
xiaowu first Lua

​ 我们也可以将代码修改为如下形式来执行脚本(在开头添加:#!/usr/local/bin/lua):

#!/usr/local/bin/lua
print("hello world!")
print("xiaowu first Lua")

​ 以上代码中,我们指定了 Lua 的解释器 /usr/local/bin directory。加上 # 号标记解释器会忽略它。接下来我们为脚本添加可执行权限,并执行:

[root@bogon lua-5.4.1]# ./hello.lua
hello world!
xiaowu first Lua

注意:
[root@bogon lua-5.4.1]# ./lua.lua
-bash: ./lua.lua: /usr/local/bin/lua^M: 坏的解释器: 没有那个文件或目录
[root@bogon lua-5.4.1]#

  • **原因:**由于windows系统下换行符为 \r\n,linux下换行符为 \n,所以导致在windows下编写的文件会比linux下多回车符号 \r。

  • **解决方法:**只需要去掉多余的 \r 回车符 即可。操作办法可以用sed命令进行全局替换。

    [root@bogon lua-5.4.1]# sed 's/\r//' -i lua.lua
    [root@bogon lua-5.4.1]# ./lua.lua
    1
    xiaowu
    

    也可以用vim来重新编辑脚本,使用vim首先查看文件格式:

    [root@bogon lua-5.4.1]# vi lua.lua
    #!/usr/local/bin/lua
    print(1)
    print("xiaowu")
    ~
    ------在底行模式下输入set ff,回车可以看到文件格式为dos----
    :set ff
    ------显示结果-----
    fileformat=dos
    
    ------修改文件格式为 unix即可------
    ------底行模式下输入set ff=unix------
    :set ff=unix
    ------保存退出即可------
    

2.3 注释|标识符

--单行注释

--[[
多行注释
]]--

​ Lua 标示符用于定义一个变量,函数获取其他用户定义的项。标示符以一个字母 A 到 Z 或 a 到 z 或下划线 _ 开头后加上 0 个或多个字母,下划线,数字(0 到 9)。

​ 最好不要使用下划线加大写字母的标示符,因为Lua的保留字也是这样的。

​ Lua 不允许使用特殊字符如 @, $, 和 % 来定义标示符。 Lua 是一个区分大小写的编程语言。因此在 Lua 中 Runoob 与 runoob 是两个不同的标示符。以下列出了一些正确的标示符:

mohd         zara      abc     move_name    a_123
myname50     _temp     j       a23b9        retVal

3、Lua数据类型

​ Lua 是动态类型语言,变量不要类型定义,只需要为变量赋值。 值可以存储在变量中,作为参数传递或结果返回。

​ Lua 中有 8 个基本类型分别为:nil、boolean、number、string、userdata、function、thread 和 table。

数据类型描述
nil这个最简单,只有值nil属于该类,表示一个无效值(在条件表达式中相当于false)。
boolean包含两个值:false和true。
number表示双精度类型的实浮点数
string字符串由一对双引号或单引号来表示
function由 C 或 Lua 编写的函数
userdata表示任意存储在变量中的C数据结构
thread表示执行的独立线路,用于执行协同程序
tableLua 中的表(table)其实是一个"关联数组"(associative arrays),数组的索引可以是数字、字符串或表类型。在 Lua 里,table 的创建是通过"构造表达式"来完成,最简单构造表达式是{},用来创建一个空表。
--[[
 nil(空) nil 类型表示一种没有任何有效值,它只有一个值 -- nil,例如打印一个没有赋值的变量,便会输出一个 nil 值:
 对于全局变量和 table,nil 还有一个"删除"作用,给全局变量或者 table 表里的变量赋一个 nil 值,等同于把它们删掉
]]--
tab1 = { key1 = "val1", key2 = "val2"}
for k, v in pairs(tab1) do
    print(k .. " - " .. v)
end
print("---------------------")
tab1.key1 = nil
for k, v in pairs(tab1) do
    print(k .. " - " .. v)
end

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

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

--[[
number(数字)
Lua 默认只有一种 number 类型 -- double(双精度)类型(默认类型可以修改 luaconf.h 里的定义)
]]--
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))

--[[
string(字符串)
字符串由一对双引号或单引号来表示。
]]--
string1 = "this is string1"
--也可以用 2 个方括号 "[[]]" 来表示"一块"字符串。
string2=[[
第一行
第二行
第三行
]]
print(string1)
print(string2)
--在对一个数字字符串上进行算术操作时,Lua 会尝试将这个数字字符串转成一个数字:
print("2" + 6)
print("2" + "6")
print("2 + 6")
print("-2e2" * "6")
--print("error" + 1)
--以上代码中"error" + 1执行报错了,字符串连接使用的是 .. ,如:
print("a" .. 'b')
print(157 .. 428)
--使用 # 来计算字符串的长度,放在字符串前面,如下实例:
len = "xiaowu"
print(#len)
print(#"xiaowu")

--[[
table(表)
在 Lua 里,table 的创建是通过"构造表达式"来完成,最简单构造表达式是{},用来创建一个空表。也可以在表里添加一些数据,直接初始化表:
]]--
-- 创建一个空的 table,-- 直接初始表
local tbl1 = {}
local tbl2 = {"apple", "pear", "orange", "grape"}
--Lua 中的表(table)其实是一个"关联数组"(associative arrays),数组的索引可以是数字或者是字符串。
--不同于其他语言的数组把 0 作为数组的初始索引,在 Lua 里表的默认初始索引一般以 1 开始。
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

--[[
function(函数)
在 Lua 中,函数是被看作是"第一类值(First-Class Value)",函数可以存在变量里:
]]--
function factorial1(n)
    if n == 0 then
        return 1
    else
        return n + 5
    end
end
print(factorial1(5))
factorial2 = factorial1
print(factorial2(5))
--function 可以以匿名函数(anonymous function)的方式通过参数传递:
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
);

4、Lua 变量

  • 变量在使用前,需要在代码中进行声明,即创建该变量。
  • 编译程序执行代码之前编译器需要知道如何给语句变量开辟存储区,用于存储变量的值。
  • Lua 变量有三种类型:全局变量、局部变量、表中的域。
  • Lua 中的变量全是全局变量,哪怕是语句块或是函数里,除非用 local 显式声明为局部变量。
  • 局部变量的作用域为从声明位置开始到所在语句块结束。
  • 变量的默认值均为 nil。
a = 5               -- 全局变量
local b = 5         -- 局部变量
function joke()
    c = 5           -- 全局变量
    local d = 6     -- 局部变量
end
joke()
print("c=",c,"d=",d)          --> 5 nil
do
    local a = 6     -- 局部变量
    b = 6           -- 对局部变量重新赋值
    print("a=",a,"b=",b);     --> 6 6
end
print("a=",a,"b=",b)      --> 5 6

--遇到赋值语句Lua会先计算右边所有的值然后再执行赋值操作,所以我们可以这样进行交换变量的值:
x, y = 1, 2
print("x =", x, "y =", y)
x, y = y, x
print("x =", x, "y =", y)
a = {}
a[1], a[2] = 3, 4
print("a[i] =", a[1], "a[j] =", a[2])
a[1], a[2] = a[2], a[1]
print("a[i] =", a[1], "a[j] =", a[2])
print("a[i] =",a[1],"a[j] =",a[2])

--多值赋值经常用来交换变量,或将函数调用返回给变量:
function testNumber()
    return 1, 2
end
number1, number2 = testNumber()
print("number1 =", number1, "number2 =", number2)

--对 table 的索引使用方括号 []。Lua 也提供了 . 操作。
site = {key = "小武", key1="小红"}
print(site["key"])
print(site.key1)

5、Lua 循环

5.1 Lua 语言提供了以下几种循环处理方式:

循环类型描述
while 循环在条件为 true 时,让程序重复地执行某些语句。执行语句前会先检查条件是否为 true。
for 循环重复执行指定语句,重复次数可在 for 语句中控制。
repeat…until重复执行循环,直到 指定的条件为真时为止。
--while
a = 10
while (a < 20)
do
    print("a 的值为:", a)
    a = a + 1
end

--for
function f(x)
    print("function")
    return x * 2
end
for i = 1, f(5) do
    print(i)
end

-- 泛型for循环
days = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }
for i, v in ipairs(days) do
    print(i, v)
end

--repeat...until 循环
a = 10
repeat
    print("a的值为:", a)
    a = a + 1
until( a > 15 )

5.2循环控制语句

循环控制语句用于控制程序的流程, 以实现程序的各种结构方式。

Lua 支持以下循环控制语句:

控制语句描述
break 语句退出当前循环或语句,并开始脚本执行紧接着的语句。
goto 语句将程序的控制点转移到一个标签处。

重点说明一下goto:Lua 语言中的 goto 语句允许将控制流程无条件地转到被标记的语句处。

for i=1,3 do
    if i <= 2 then
        print(i,"yess")
        goto xiaowu
    end
    print(i,"noss")
    ::xiaowu::
    print("end")
end

6、Lua 流程控制

语句描述
if 语句if 语句 由一个布尔表达式作为条件判断,其后紧跟其他语句组成。
if…else 语句if 语句 可以与 else 语句搭配使用, 在 if 条件表达式为 false 时执行 else 语句代码。
if 嵌套语句你可以在ifelse if中使用一个或多个 ifelse if 语句 。
a = 100
if (a==100) then
    print("条件为true")
end

if (a==10) then
    print("条件为true")
else
    print("条件为false")
end


if( a==10 )
then
    print("a 的值为 10" )
elseif( a==20 )
then
    print("a 的值为 20" )
elseif( a==30 )
then
    print("a 的值为 30" )
else
    print("没有匹配 a 的值" )
end
print("a 的真实值为: ", a )

7、Lua 函数

在Lua中,函数是对语句和表达式进行抽象的主要方法。既可以用来处理一些特殊的工作,也可以用来计算一些值。

Lua 提供了许多的内建函数,你可以很方便的在程序中调用它们,如print()函数可以将传入的参数打印在控制台上。

Lua 函数主要有两种用途:

  • 1.完成指定的任务,这种情况下函数作为调用语句使用;
  • 2.计算并返回值,这种情况下函数作为赋值语句的表达式使用。

7.1函数定义

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

7.2 实例

function max(num1,num2)
    if(num1>num2) then
        return num1
    else
        return num2
    end
end
print("最大值",max(10,2))
print("最大值",max(1,2))

-- Lua 中我们可以将函数作为参数传递给函数,如下实例:
myAdd=function(num1,num2)
    return num2+num1
end
print("num1+num2=",myAdd(1,2))

mySub=function(num1,num2)
    return num2-num1
end
print("num1+num2=",mySub(1,2))

myPrint=function(num1,num2,myAdd)
    print("num1+num2=",myAdd(num1,num2))
end

myPrint(2,3,myAdd)
myPrint(2,3,mySub)

-- 多返回值Lua函数可以返回多个结果值,其返回匹配串"开始和结束的下标"(如果不存在匹配串返回nil)。
function getResult(num1,num2)
    return num1+num2,num2-num1,num1*num2
end
_add,_sub,_mul,_div=getResult(2,3)
print("_add",_add,"_sub",_sub,"_mul",_mul,"_div",_div)

--可变参数Lua 函数可以接受可变数目的参数,和 C 语言类似,在函数参数列表中使用三点 ... 表示函数有可变的参数。
function addFirst(...)
    local sum=0
    for k,v in ipairs { ... } do
        sum=sum+v
        print(k,v)
    end
    return sum
end
print(addFirst(1,2,3,4,5))
-- 有时候我们可能需要几个固定参数加上可变参数,固定参数必须放在变长参数之前:
function addFirst(num1,...)
    for k,v in ipairs { ... } do
        num1=num1+v
        print(k,v)
    end
    return num1
end

8、Lua 运算符

运算符是一个特殊的符号,用于告诉解释器执行特定的数学或逻辑运算。Lua提供了以下几种运算符类型:

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

8.1 算式运算符

设定 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
8.2 关系运算符

设定 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。
8.3 逻辑运算符

设定 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。
8.4 其他运算符
操作符描述实例
连接两个字符串a…b ,其中 a 为 "Hello " , b 为 “World”, 输出结果为 “Hello World”。
#一元运算符,返回字符串或表的长度。#“Hello” 返回 5
8.5 运算符优先级,从高到低的顺序:
^
not    - (unary)
*      /       %
+      -
..
<      >      <=     >=     ~=     ==
and
or
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐