【Lua】Lua 基础语法

文章目录

前言:本文内容大部分摘抄自 菜鸟教程

Lua 语法学习推荐文章:CSDN - 董哥的黑板报

Lua 脚本

在代码开头添加:#!/usr/local/bin/lua,然后给 xxx.lua 添加可执行权限即可。

注释

单行注释:

lua 复制代码
--

多行注释:

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 可以对多个变量同时赋值,变量列表和值列表的各个元素用逗号分开

    lua 复制代码
    a, b = 10, 2*x       <-->       a=10; b=2*x
    
    a, b = 0, 1
    a, b = a+1, a+1
    print(a,b)               --> 1   1
  • 遇到赋值语句 Lua 会先计算右边所有的值 (等号右边的值) 然后再执行赋值操作 -- 表达式右边是值而不是变量,所以我们可以这样进行交换变量的值:

    lua 复制代码
    a, b = b, a
  • 在访问数组索引时,Lua 支持 [],也支持 .,便于字符串操作:

    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 编程语言函数定义格式如下:

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 函数不需要定义返回值类型,且可以返回多个值,多个值之间使用逗号分隔。

可变参数

Lua 函数可以接受可变数目的参数,和 C 语言类似,在函数参数列表中使用三点 ... 表示函数有可变的参数。

lua 复制代码
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

我们可以将可变参数赋值给一个变量:

lua 复制代码
local args = {...}

我们可以通过如下方式来获取可变参数的数量:

lua 复制代码
local arg={...}
print(#arg)
print(select("#",...))

通常在遍历变长参数的时候只需要使用 {...} ,然而变长参数可能会包含一些 nil ,那么就可以用 select 函数来访问变长参数:

  • select('#', ...) 返回可变参数的长度。
  • select(n, ...) 用于返回从起点 n 开始到结束位置的所有参数列表。
lua 复制代码
function f(...)
    a = select(3,...)  -->从第三个位置开始,变量 a 对应右边变量列表的第一个参数
    print (a)
    print (select(3,...)) -->打印所有列表参数
end

f(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 来实现数组功能:

lua 复制代码
local arr = {1, 2, 3, 4, 5}

Lua 数组的索引从 1 开始,同时,数组大小是动态扩容的,因此不需要考虑越界访问和赋值的问题 -- 越界访问返回 nil,越界赋值会自动扩容。

需要注意的是,与 C/C++ 不同,Lua 数组中的元素必须全部显示赋值,否则为 nil,不会像 C/C++ 那样自动初始化:

lua 复制代码
-- C/C++
int arr[5] = { 1 };    ==> 1,0,0,0,0
-- lua
arr = { 1, 2 }
arr[4] = 4             ==> 1,2,nil,4

一维数组:

lua 复制代码
-- 创建一个数组
local myArray = {10, 20, 30, 40, 50}

-- 添加新元素到数组末尾
myArray[#myArray + 1] = 60

-- 循环遍历数组
for i = 1, #myArray do
    print(myArray[i])
end

二维数组:

lua 复制代码
-- 初始化数组 -- 三行三列
array = {}
for i=1,3 do
   array[i] = {}
      for j=1,3 do
         array[i][j] = i*j
      end
end

-- 访问数组
for i=1,3 do
   for j=1,3 do
      print(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 就行。

lua 复制代码
-- 文件名为 module.lua
-- 定义一个名为 module 的模块
module = {}
 
-- 定义一个常量
module.constant = "这是一个常量"
 
-- 定义一个函数
function module.func1()
    io.write("这是一个公有函数!\n")
end
 
local function func2()
    print("这是一个私有函数!")
end
 
function module.func3()
    func2()
end
 
return module

加载模块:

lua 复制代码
require("<模块名>") or require "<模块名>" or local m = require("module")

加载完毕后直接使用就行 -- 模块的定义与使用与 table 一样:

lua 复制代码
-- test_module.lua 文件
-- module 模块为上文提到到 module.lua
require("module")
 
print(module.constant)
 
module.func3()

需要注意的是,Lua 使用 package.pathpackage.cpath 来查找模块的位置。这两个变量分别用于查找 Lua 脚本模块(.lua 文件)和 C 库模块(.so.dll 文件)。

因此,对于自定义模块,我们需要修改 package.path 来添加自定义的模块查找路径:

lua 复制代码
package.path = package.path .. ";~/lua/module.lua"

local mymodule = require("mymodule")  -- Lua 会在指定路径中查找模块

相关推荐
@Sunset...5 小时前
热更新解决方案4——xLua热补丁
unity·c#·lua
小佟2 天前
postman-9.12.2–安装包及汉化
开发语言·lua
雅典没有娜2 天前
QT/C++与LUA交互过程中,利用ZeroBraneStudio对LUA脚本进行仿真调试
c++·qt·lua·调试·仿真·zerobranestudio
@Sunset...2 天前
热更新解决方案3 —— xLua
开发语言·unity·c#·游戏引擎·lua
键盘会跳舞4 天前
【Qt项目实战】使用脚本拓展CPP应用程序(2)——Lua脚本及编辑器
qt·编辑器·lua
一头生产的驴6 天前
springboot整合lua脚本在Redis实现商品库存扣减
java·spring boot·redis·lua
三月天明6 天前
服务器批量清理redis keys,无法适用客户端必须直连的情况
运维·服务器·redis·lua
1-programmer6 天前
apisix lua插件开发记录
lua·apisix
willhuo6 天前
luatos fskv数据库操作
单片机·lua