Power Node (Dynamic Brother Video) Redis7 Notes - Chapter 8 Detailed Explanation of Luau Script

8 Detailed explanation of Lua script

8.1 Introduction to Lua

Lua is an open source, extensible, lightweight, weakly typed, interpreted scripting language developed by the standard C language.

8.2 Lua in Linux system

8.2.1 Lua download

If you want to use Lua, you need to download its source code from the official website and install it.

8.2.2 Lua installation

First upload the downloaded Lua source code to Linux, and then install it.

8.2.2.1 Decompression

Unzip the Lua source code to the /opt/apps directory.

Enter the lua directory under /opt/apps to see the Makefile for compilation and the source code directory src.

8.2.2.2 Install gcc

Since Lua is written in C/C++ language, it is necessary to use a relevant compiler to compile it. For C/C++ language compilers, gcc is the most used.

8.2.2.3 Compile

Execute the compile command make linux test.

8.2.2.4 Installation


After the installation is complete, you can view the version number through lua –v, which is the same as the last result displayed in the previous make linux test.

8.2.3 Hello World

8.2.3.1 Two interaction modes

Lua provides users with two interactive modes: command line mode and script file mode.

8.2.3.1.1 Command line mode

In this mode, you can directly enter the statement in the command line and press Enter to see the running result.

Use the lua command in any directory to enter the lua command line mode, enter the statement and press Enter to run it and display the result. Use Ctrl+C to exit the mode.
It should be noted that lua's requirement for the semicolon after the statement is not mandatory, and it doesn't matter if it is present or not.

8.2.3.1.2 Script file mode

This mode is to write the script file first, and then use the lua command to run the file.
For example, create a script directory in the current user's home directory, create a file named hello.lua in it, and write a print() statement in the file.


Then run the "lua script file" directly to see the result.

8.2.3.2 Two script running modes

There are two ways to run the script file. One is the lua command method above, and the other is the executable file method. The executable file method is to directly modify the lua script file to run as an executable file.
The following uses the second method to run.

8.2.3.2.1 Modify script file content

Add #!/usr/bin/lua to the first line of the script file, indicating that the current file will use the /usr/bin/lua command to run.

8.2.3.2.2 Modify script file permissions

Give executable permission to the script file.

8.2.3.2.3 Running

Just use the filename to run it.

8.3 Lua in Win system

What is to be installed here is the operating environment of Lua in the Windows system. The most commonly used is SciTE.
SciTE is a Lua script test editor that provides an editing and running environment for Lua. SciTE provides two running modes: command line window running mode and Lua script editing and running environment.
In addition to SciTE, there are LuaDist, LuaRocks, etc.

8.3.1 x

8.4 Lua Grammar Basics

8.4.1 Notes

Lua的行注释为两个连续的减号,段注释以--[[开头,以--]]结尾。

However, if you want to temporarily cancel the segment comment during debugging, and directly delete its mark, it is actually not good to do so. Because it may need to be added. The writing of paragraph comments is relatively troublesome. Therefore, Lua gives a simple way to deal with it: add a minus sign before the beginning –[[ to disable the segment comment. In fact, it turns the two segment comment tags into two line comments.

8.4.2 Data types

There are 8 types in Lua, namely: nil, boolean, number, string, userdata, function, thread and table. The type of a data can be viewed through the type() function, for example, the result of type(nil) is nil, and the result of type(123) is number.

type of data describe
nil Only the value nil belongs to this class, representing an invalid value, similar to null in Java. But it is equivalent to false in conditional expressions.
boolean Contains two values: false and true.
number Represents a real floating-point number of type double.
string String, enclosed by a pair of double or single quotes. When a string contains multiple lines, it can start with [[ in the first line and end with ]] in the last line, then the content of the multiple lines enclosed in [[ and ]] is a string. The newline character is the string "\n".
table Similar to arrays in Java, but more powerful and flexible than arrays.
function Functions written in C or Lua.
thread The cooperative thread is the execution body of the cooperative function, that is, the cooperative function that is being executed.
userdata A user-defined data, which is used to represent a type created by an application program or a C/C++ language library, and any data of any C/C++ data type can be stored in a Lua variable and called.

8.4.3 Identifiers

Identifiers in programming languages ​​mainly include reserved words, variables, constants, method names, function names, class names, etc. Lua identifiers are composed of letters, numbers and underscores, but cannot start with a number. Lua is case sensitive.

8.4.3.1 Reserved words

There are 22 common reserved words in Lua. However, in addition to these 22, there are many built-in global variables defined in Lua. A common feature of these built-in global variables is that they start with an underscore and are followed by all capital letters. So we cannot repeat these reserved words and built-in global variables when defining our own identifiers.

and break do else
elseif end false for
function if in local
nil not or repeat
return then true until
while goto

8.4.3.2 Variables

Lua is a weakly typed language, variables can be used directly without type declaration. Variables are divided into global variables and local variables. Variables in Lua are global variables by default, even if they are declared in statement blocks or functions. Once a global variable is declared, it can be accessed anywhere in the current file. The local variable local is equivalent to the private variable in Java and can only be used in the declared statement block.

8.4.3.3 Dynamic typing

Lua is a dynamically typed language, and the type of a variable can be changed at any time without declaration.

8.4.4 Operators

An operator is a special symbol used to tell the interpreter to perform a specific mathematical or logical operation. Lua provides the following operator types:

  • arithmetic operator
  • relational operator
  • Logical Operators
  • other operators

8.4.4.1 Arithmetic operators

The following table lists common arithmetic operators in Lua language, set the value of A to 10, and the value of B to 20:

operator describe example
+ addition A + B output result 30
- subtraction A - B output result -10
* multiplication A * B output result 200
/ division 5 / 2 output result 2.5
% Take the remainder B % A output result 0
^ Exponentiation A^2 output result 100
- negative -A output result -10
// Integer division operator (>=lua5.3) 5//2 output result 2


Notice,

  • The current highest version supported by SciTE for Lua is 5.1, and the integer division operator // needs to be above Lua5.3, so the effect cannot be seen in the current SciTE.
  • In the command line mode, directly enter the variable name and press Enter, which is equivalent to the print() function to output the variable.

8.4.4.2 Relational operators

The following table lists the common relational operators in Lua language, set the value of A to 10, and the value of B to 20:

operator describe example
== equal (A == B) is false.
~= not equal to (A ~= B) is true.
> more than the (A > B) is false.
< less than (A < B) is true.
>= greater or equal to (A >= B) returns false.
<= less than or equal to (A <= B) returns true.

8.4.4.3 Logical operators

Note that the Lua system treats false and nil as false, true and non-nil as true, even 0 is true.
The following table lists common logical operators in Lua language, set the value of A to true and the value of B to false:

operator describe example
and logic and (A and B) is false.
or logical or (A or B) 为 true。
not logical NOT not(A and B) 为 true。

8.4.4.4 Other operators

The following table lists the concatenation operators and operators for calculating the length of a table or string in the Lua language:

operator describe example
(two dots) String concatenation. a…b, where a is "Hello ", b is "World", and the output result is "Hello World".
# Returns the length of a string or table. #"Hello" returns 5.

8.4.5 Functions

Lua中函数的定义是以function开头,后跟函数名与参数列表,以end结尾。其可以没有返回值,也可以一次返回多个值。

8.4.5.1 固定参函数

Lua中的函数在调用时与Java语言中方法的调用是不同的,其不要求实参的个数必须与函数中形参的个数相同。如果实参个数少于形参个数,则系统自动使用nil填充;如果实参个数多于形参个数,多出的将被系统自动忽略。

8.4.5.2 可变参函数

在函数定义时不给出具体形参的个数,而是使用三个连续的点号。在函数调用时就可以向该函数传递任意个数的参数,函数可以全部接收。

8.4.5.3 可返回多个值

Lua中的函数一次可以返回多个值,但需要有多个变量来同时接收。

8.4.5.4 函数作为参数

Lua的函数中,允许函数作为参数。而作为参数的函数,可以是已经定义好的普通函数,也可以是匿名函数。

8.4.6 流程控制语句

Lua提供了if作为流程控制语句。

8.4.6.1 if语句

Lua提供了if…then用于表示条件判断,其中if的判断条件可以是任意表达式。Lua系统将false与nil作为假,将true与非nil作为真,即使是0也是真。
需要注意,Lua中的if语句的判断条件可以使用小括号括起来,也可以不使用。

8.4.6.2 if嵌套语句

Lua中提供了专门的关键字elseif来做if嵌套语句。注意,不能使用else与if两个关键字的联用形式,即不能使用else if来嵌套if语句。

8.4.7 循环控制语句

Lua提供了四种循环控制语句:while…do循环、repeat…until循环、数值for循环,及泛型for循环。同时,Lua还提供了break与goto两种循环流程控制语句。

8.4.7.1 while…do

只要while中的条件成立就一直循环。

8.4.7.2 repeat…until

until中的条件成立了,循环就要停止。

8.4.7.3 数值for

这种for循环只参用于循环变量为数值型的情况。其语法格式为:
for var=exp1, exp2, exp3 do
循环体
end
var为指定的循环变量,exp1为循环起始值,exp2为循环结束值,exp3为循环步长。步长可省略不写,默认为1。每循环一次,系统内部都会做一次当前循环变量var的值与exp2的比较,如果var小于等于exp2的值,则继续循环,否则结束循环。

8.4.7.4 泛型for

泛型for用于遍历table中的所有值,其需要与Lua的迭代器联合使用。后面table学习时再详解。

8.4.7.5 break

break语句可以提前终止循环。其只能用于循环之中。

8.4.7.6 goto

goto语句可以将执行流程无条件地跳转到指定的标记语句处开始执行,注意,是开始执行,并非仅执行这一句,而是从这句开始后面的语句都会重新执行。当然,该标识语句在第一次经过时也是会执行的,并非是必须由goto跳转时才执行。
语句标记使用一对双冒号括起来,置于语句前面。goto语句可以使用在循环之外。
注意,Lua5.1中不支持双冒号的语句标记。

8.5 Lua语法进阶

8.5.1 table

8.5.1.1 数组

使用table可以定义一维、二维、多维数组。不过,需要注意,Lua中的数组索引是从1开始的,且无需声明数组长度,可以随时增加元素。当然,同一数组中的元素可以是任意类型。

8.5.1.2 map

使用table也可以定义出类似map的key-value数据结构。其可以定义table时直接指定key-value,也可单独指定key-value。而访问时,一般都是通过table的key直接访问,也可以数组索引方式来访问,此时的key即为索引。

8.5.1.3 混合结构

Lua允许将数组与key-value混合在同一个table中进行定义。key-value不会占用数组的数字索引值。

8.5.1.4 table操作函数

Lua中提供了对table进行操作的函数。

8.5.1.4.1 table.concat()

【函数】table.concat (table [, sep [, start [, end]]]):
【解析】该函数用于将指定的table数组元素进行字符串连接。连接从start索引位置到end索引位置的所有数组元素, 元素间使用指定的分隔符sep隔开。如果table是一个混合结构,那么这个连接与key-value无关,仅是连接数组元素。

8.5.1.4.2 table.unpack()

【函数】table.unpack (table [, i [, j]])
【解析】拆包。该函数返回指定table的数组中的从第i个元素到第j个元素值。i与j是可选的,默认i为1,j为数组的最后一个元素。Lua5.1不支持该函数。

8.5.1.4.3 table.pack()

【函数】table.pack (…)
【解析】打包。该函数的参数是一个可变参,其可将指定的参数打包为一个table返回。这个返回的table中具有一个属性n,用于表示该table包含的元素个数。Lua5.1不支持该函数。

8.5.1.4.4 table.maxn()

【函数】table.maxn(table)
【解析】该函数返回指定table的数组中的最大索引值,即数组包含元素的个数。

8.5.1.4.5 table.insert()

【函数】table.insert (table, [pos,] value):
【解析】该函数用于在指定table的数组部分指定位置pos插入值为value的一个元素。其后的元素会被后移。pos参数可选,默认为数组部分末尾。

8.5.1.4.6 table.remove ()

【函数】table.remove (table [, pos])
【解析】该函数用于删除并返回指定table中数组部分位于pos位置的元素。其后的元素会被前移。pos参数可选,默认删除数组中的最后一个元素。

8.5.1.4.7 table.sort()

【函数】table.sort(table [,fun(a,b)])
【解析】该函数用于对指定的table的数组元素进行升序排序,也可按照指定函数fun(a,b)中指定的规则进行排序。fun(a,b)是一个用于比较a与b的函数,a与b分别代表数组中的两个相邻元素。
注意:

  • 如果arr中的元素既有字符串又有数值型,那么对其进行排序会报错。
  • 如果数组中多个元素相同,则其相同的多个元素的排序结果不确定,即这些元素的索引谁排前谁排后,不确定。
  • 如果数组元素中包含nil,则排序会报错。

8.5.2 迭代器

Lua提供了两个迭代器pairs(table)与ipairs(table)。这两个迭代器通常会应用于泛型for循环中,用于遍历指定的table。这两个迭代器的不同是:

  • ipairs(table):仅会迭代指定table中的数组元素。
  • pairs(table):会迭代整个table元素,无论是数组元素,还是key-value。

8.5.3 模块

模块是Lua中特有的一种数据结构。从 Lua 5.1 开始,Lua 加入了标准的模块管理机制,可以把一些公用的代码放在一个文件里,以 API 接口的形式在其他地方调用,有利于代码的重用和降低代码耦合度。
模块文件主要由table组成。在table中添加相应的变量、函数,最后文件返回该table即可。如果其它文件中需要使用该模块,只需通过require将该模块导入即可。

8.5.3.1 定义一个模块

模块是一个lua文件,其中会包含一个table。一般情况下该文件名与该table名称相同,但其并不是必须的。

8.5.3.2 使用模块

这里要用到一个函数require(“文件路径”),其中文件名是不能写.lua扩展名的。该函数可以将指定的lua文件静态导入(合并为一个文件)。不过需要注意的是,该函数的使用可以省略小括号,写为require “文件路径”。
require()函数是有返回值的,返回的就是模块文件最后return的table。可以使用一个变量接收该table值作为模块的别名,就可以使用别名来访问模块了。

8.5.3.3 再看模块

模块文件中一般定义的变量与函数都是模块table相关内容,但也可以定义其它与table无关的内容。这些全局变量与函数就是普通的全局变量与函数,与模块无关,但会随着模块的导入而同时导入。所以在使用时可以直接使用,而无需也不能添加模块名称。

8.5.4 元表与元方法

元表,即Lua中普通table的元数据表,而元方法则是元表中定义的普通表的默认行为。Lua中的每个普通table都可为其定义一个元表,用于扩展该普通table的行为功能。例如,对于table与数值相加的行为,Lua中是没有定义的,但用户可通过为其指定元表来扩展这种行为;再如,用户访问不存在的table元素,Lua默认返回的是nil,但用户可能并不知道发生了什么。此时可以通过为该table指定元表来扩展该行为:给用户提示信息,并返回用户指定的值。

8.5.4.1 重要函数

元表中有两个重要函数:

  • setmetatable(table,metatable):将metatable指定为普通表table的元表。
  • getmetatable(table):获取指定普通表table的元表。

8.5.4.2 _ _index元方法

当用户在对table进行读取访问时,如果访问的数组索引或key不存在,那么系统就会自动调用元表的_ index元方法。该重写的方法可以是一个函数,也可以是另一个表。如果重写的 _index元方法是函数,且有返回值,则直接返回;如果没有返回值,则返回nil。

8.5.4.3 _ _newindex元方法

当用户为table中一个不存在的索引或key赋值时,就会自动调用元表的_ newindex元方法。该重写的方法可以是一个函数,也可以是另一个表。如果重写的 _newindex元方法是函数,且有返回值,则直接返回;如果没有返回值,则返回nil。

8.5.4.4 运算符元方法

如果要为一个表扩展加号(+)、减号(-)、等于(==)、小于(<)等运算功能,则可重写相应的元方法。
例如,如果要为一个table扩展加号(+)运算功能,则可重写该table元表的_ add元方法,而具体的运算规则,则是定义在该重写的元方法中的。这样,当一个table在进行加法(+)运算时,就会自动调用其元表的 _add元方法。

类似于加法操作的其它操作,Lua中还包含很多:

元方法 说明 元方法 说明
__add 加法,+ __band 按位与,&
__sub 减法,- __bor 按位或,|
__mul 乘法,* __bxor 按位异或,~
__div 除法,/ __bnot 按位非,~
__mod 取模,% __shl 按位左移,<<
__pow 次幂,^ __shr 按位右移,>>
__unm 取反,-
__idiv 取整除法,// __eq 等于,==
__lt 小于,<
__concat 字符串连接,… __le 小于等于,<=
__len 字符串长度,#

8.5.4.5 _ _tostring元方法

直接输出一个table,其输出的内容为类型与table的存放地址。如果想让其输出table中的内容,可重写_ _tostring元方法。


8.5.4.6 _ _call元方法

当将一个table以函数形式来使用时,系统会自动调用重写的_ _call元方法。该用法主要是可以简化对table的相关操作,将对table的操作与函数直接相结合。

8.5.4.7 元表单独定义

为了便于管理与复用,可以将元素单独定义为一个文件。该文件中仅可定义一个元表,且一般文件名与元表名称相同。
若一个文件要使用其它文件中定义的元表,只需使用require “元表文件名”即可将元表导入使用。
如果用户想扩展该元表而又不想修改元表文件,则可在用户自己文件中重写其相应功能的元方法即可。

8.5.5 面向对象

Lua中没有类的概念,但通过table、function与元表可以模拟和构造出具有类这样功能的结构。

8.5.5.1 简单对象的创建

Lua中通过table与fcuntion可以创建出一个简单的Lua对象:table为Lua对象赋予属性,通过function为Lua对象赋予行为,即方法。

8.5.5.2 类的创建

Lua中使用table、function与元表可以定义出类:使用一个表作为基础类,使用一个function作为该基础类的new()方法。在该new()方法中创建一个空表,再为该空表指定一个元表。该元表重写_ index元方法,且将基础表指定为重写的 _index元方法。由于new()中的表是空表,所以用户访问的所有key都会从基础类(表)中查找。

8.5.6 协同线程与协同函数

8.5.6.1 协同线程

Lua中有一种特殊的线程,称为coroutine,协同线程,简称协程。其可以在运行时暂停执行,然后转去执行其它线程,然后还可返回再继续执行没有执行完毕的内容。即可以“走走停停,停停再走走”。
协同线程也称为协作多线程,在Lua中表示独立的执行线程。任意时刻只会有一个协程执行,而不会出现多个协程同时执行的情况。
协同线程的类型为thread,其启动、暂停、重启等,都需要通过函数来控制。下表是用于控制协同线程的基本方法。

方法 描述
create(function) 创建一个协同线程实例,即返回的是thread类型。参数是一个function。其需要通过resume()来启动协同线程的执行
resume(thread, …) 启动指定的协同线程的执行,使其从开始处或前面挂起处开始执行。可以向create()的内置函数传递相应的参数。如果内置函数具有返回值,resume()会全部接收并返回。
running() 返回正在运行的协同线程实例,即thread类型值
yield() 挂起协同线程,并将协同线程设置为挂起状态。resume()可从挂起处重启被挂起的协同线程
status(thread) 查看协同线程的状态。状态有三种:运行态running,挂起态suspended,消亡态dead
close() 关闭协同线程
wrap(function) 创建一个协同函数,返回的是function类型。一旦调用该函数就会创建并执行一个协同线程实例

8.5.6.2 协同函数

协同线程可以单独创建执行,也可以通过协同函数的调用启动执行。使用coroutine的wrap()函数创建的就是协同函数,其类型为function。
由于协同函数的本质就是函数,所以协同函数的调用方式就是标准的函数调用方式。只不过,协同函数的调用会启动其内置的协同线程。

8.5.7 文件IO

Lua中提供了大量对文件进行IO操作的函数。这些函数分为两类:静态函数与实例函数。所谓静态函数是指通过io.xxx()方式对文件进行操作的函数,而实例函数则是通过Lua中面向对象方式操作的函数。

8.5.7.1 常用静态函数

8.5.7.1.1 io.open()

【格式】io.open (filename [, mode])
【解析】以指定模式打开指定文件,返回要打开文件的句柄,就是一个对象(后面会讲Lua中的对象)。其中模式mode有三种,但同时还可配合两个符号使用:

  • r:只读,默认模式
  • w:只写,写入内容会覆盖文件原有内容
  • a:只写,以追加方式写入内容
  • +:增加符,在r+、w+、a+均变为了读写
  • b:二进制表示符。如果要操作的文件为二进制文件,则需要变为rb、wb、ab。
8.5.7.1.2 io.input()

【格式】io.input (file)
【解析】指定要读取的文件。

8.5.7.1.3 io.output()

【格式】io.output (file)
【解析】指定要写入的文件。

8.5.7.1.4 io.read()

【格式】io.read([format])
【解析】以指定格式读取io.input()中指定的输入文件。其中format格式有:

  • *l:从当前位置的下一个位置开始读取整个行,默认格式
  • *n:读取下一个数字,其将作为浮点数或整数
  • *a:从当前位置的下一个位置开始读取整个文件
  • number:这是一个数字,表示要读取的字符的个数
8.5.7.1.5 io.write()

【格式】io.write(data)
【解析】将指定的数据data写入到io.output()中指定的输出文件。

8.5.7.2 常用实例函数

8.5.7.2.1 file:read()

这里的file使用的是io.open()函数返回的file,其实际就是Lua中的一个对象。其用法与io.read()的相同。

8.5.7.2.2 file:write()

用法与io.write()的相同。

8.5.7.2.3 file:seek()

【格式】file:seek ([whence [, offset]])
【解析】该函数用于获取或设置文件读写指针的当前位置。位置从1开始计数,除文件最后一行外,每行都有行结束符,其会占两个字符位置。位置0表示文件第一个位置的前面位置。
当seek()为无参时会返回读写指针的当前位置。参数whence的值有三种,表示将指针定位的不同位置。而offset则表示相对于whence指定位置的偏移量,offset的默认值为0,为正表示向后偏移,为负表示向前偏移。

  • set:表示将指针定位到文件开头处,即0位置处
  • cur:表示指针保持当前位置不变,默认值
  • end:表示将指针定位到文件结尾处

Guess you like

Origin blog.csdn.net/f5465245/article/details/130986883