lua学习

lua学习

环境安装

  1. linux下载源码

    sirius@slave:~$ wget http://www.lua.org/ftp/lua-5.4.0.tar.gz
    --2020-08-06 22:19:23--  http://www.lua.org/ftp/lua-5.4.0.tar.gz
    Resolving www.lua.org (www.lua.org)... 88.99.213.221, 2a01:4f8:10a:3edc::2
    Connecting to www.lua.org (www.lua.org)|88.99.213.221|:80... connected.
    HTTP request sent, awaiting response... 200 OK
    Length: 349308 (341K) [application/gzip]
    Saving to: ‘lua-5.4.0.tar.gz’
    
    lua-5.4.0.tar.gz           100%[=======================================>] 341.12K  10.3KB/s    in 29s     
    
    2020-08-06 22:19:54 (11.9 KB/s) - ‘lua-5.4.0.tar.gz’ saved [349308/349308
    
  2. 执行命令

    sirius@slave:~/lua$ make linux test
    
  3. 执行命令

    sirius@slave:~/lua$ sudo make install
    
  4. 安装验证

    sirius@slave:~/projects/luatest$ lua -i
    Lua 5.4.0  Copyright (C) 1994-2020 Lua.org, PUC-Rio
    > print("hello")
    hello
    >
    

脚本式编程

程序执行

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

print("Hello World!")

使用 lua 名执行以上脚本,输出结果为:

sirius@slave:~/projects/luatest$ vi hello.lua 
sirius@slave:~/projects/luatest$ lua hello.lua 
Hello World!

也可以以如下的形式执行

#!/usr/local/bin/lua
print("Hello World!")

然后直接执行文件

sirius@slave:~/projects/luatest$ chmod 777 hello.lua 
sirius@slave:~/projects/luatest$ ./hello.lua 
Hello World!

标识符

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

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

Lua 不允许使用特殊字符如 @, $, 和 % 来定义标示符。 Lua 是一个区分大小写的编程语言。因此在 Lua 中 sirius与 Sirius 是两个不同的标示符。

保留字

andbreakdoelse
elseifendfalsefor
functionifinlocal
nilnotorrepeat
returnthentrueuntil
whilegoto

全局变量

在默认情况下,变量总是认为是全局的。

全局变量不需要声明,给一个变量赋值后即创建了这个全局变量,访问一个没有初始化的全局变量也不会出错,只不过得到的结果是:nil。

Lua 5.4.0  Copyright (C) 1994-2020 Lua.org, PUC-Rio
> print(b)
nil
> b=10
> print(b)
10
> 

数据类型

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 的创建是通过"构造表达式"来完成,最简单构造表达式是{},用来创建一个空表。

变量

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

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

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

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

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

变量的默认值均为 nil。

循环

很多情况下我们需要做一些有规律性的重复操作,因此在程序中就需要重复执行某些语句。

一组被重复执行的语句称之为循环体,能否继续重复,决定循环的终止条件。

循环结构是在一定条件下反复执行某段程序的流程结构,被反复执行的程序被称为循环体。

循环语句是由循环体及循环的终止条件两部分组成的。

while循环

while(condition)
do
   statements
end

数组for循环

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

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

for i=10,1,-1 do
    print(i)
end

泛型for循环

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

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

for i, v in ipairs(a) do
    print(i, v)
end 

repeat…until 循环

repeat
   statements
until( condition )

循环条件判断语句(condition)在循环体末尾部分,所以在条件进行判断前循环体都会执行一次。

如果条件判断语句(condition)为 false,循环会重新开始执行,直到条件判断语句(condition)为 true 才会停止执行。

break

break 语句插入在循环体中,用于退出当前循环或语句,并开始脚本执行紧接着的语句。

如果你使用循环嵌套,break语句将停止最内层循环的执行,并开始执行的外层的循环语句。

goto

goto 语句允许将控制流程无条件地转到被标记的语句处。

语法格式如下所示:

goto Label

Label 的格式为:

:: Label ::

例子

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

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

有了 goto,我们可以实现 continue 的功能:

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

流程控制

Lua 编程语言流程控制语句通过程序设定一个或多个条件语句来设定。在条件为 true 时执行指定程序代码,在条件为 false 时执行其他指定代码。

控制结构的条件表达式结果可以是任何值,Lua认为false和nil为假,true和非nil为真。

要注意的是Lua中 0 为 true:

if(布尔表达式)
then
   --[ 在布尔表达式为 true 时执行的语句 --]
end

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

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

函数

定义

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 中我们可以将函数作为参数传递给函数,如下实例:

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

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

多返回值

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

> s, e = string.find("hello world", "hello") 
> print(s, e)
1	5
> 

可变参数

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

我们可以通过 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))
  • 通常在遍历变长参数的时候只需要使用 {…},然而变长参数可能会包含一些 nil,那么就可以用 select 函数来访问变长参数了:select(’#’, …) 或者 select(n, …)

    • select(’#’, …) 返回可变参数的长度
    • select(n, …) 用于返回 nselect(’#’,…) 的参数

字符串

字符串或串(String)是由数字、字母、下划线组成的一串字符。

Lua 语言中字符串可以使用以下三种方式来表示:

  • 单引号间的一串字符。
  • 双引号间的一串字符。
  • [[]] 间的一串字符。

字符串操作

序号方法 & 用途
1string.upper(argument): 字符串全部转为大写字母。
2string.lower(argument): 字符串全部转为小写字母。
3**string.gsub(mainString,findString,replaceString,num)**在字符串中替换。mainString 为要操作的字符串, findString 为被替换的字符,replaceString 要替换的字符,num 替换次数(可以忽略,则全部替换),如:
4string.find (str, substr, [init, [end]]) 在一个指定的目标字符串中搜索指定的内容(第三个参数为索引),返回其具体位置。不存在则返回 nil。
5string.reverse(arg) 字符串反转
6string.format(…) 返回一个类似printf的格式化字符串
7string.char(arg) 和 string.byte(arg[,int]) char 将整型数字转成字符并连接, byte 转换字符为整数值(可以指定某个字符,默认第一个字符)。
8string.len(arg) 计算字符串长度。
9string.rep(string, n) 返回字符串string的n个拷贝
10 链接两个字符串
11string.gmatch(str, pattern) 回一个迭代器函数,每一次调用这个函数,返回一个在字符串 str 找到的下一个符合 pattern 描述的子串。如果参数 pattern 描述的字符串没有找到,迭代函数返回nil。
12string.match(str, pattern, init) string.match()只寻找源字串str中的第一个配对. 参数init可选, 指定搜寻过程的起点, 默认为1。 在成功配对时, 函数将返回配对表达式中的所有捕获结果; 如果没有设置捕获标记, 则返回整个配对字符串. 当没有成功的配对时, 返回nil。

redis中使用lua

在redis里面使用lua脚本主要用三个命令

  • eval
  • evalsha
  • script load

eval

EVAL script numkeys key [key ...] arg [arg ...]
> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
1) "key1"
2) "key2"
3) "first"
4) "second"

key代表要操作的rediskey

arg可以传自定义的参数

numkeys用来确定key有几个

script就是你写的lua脚本

lua脚本里面使用KEYS[1]和ARGV[1]来获取传递的key和arg

script load和evalsha

在用eval命令的时候,可以注意到每次都要把执行的脚本发送过去,这样势必会有一定的网络开销,所以redis对lua脚本做了缓存,通过script load 和 evalsha实现

script load命令会在redis服务器缓存你的lua脚本,并且返回脚本内容的SHA1校验和,然后通过evalsha 传递SHA1校验和来找到服务器缓存的脚本进行调用,这两个命令的格式以及使用方式如下

SCRIPT LOAD script
EVALSHA sha1 numkeys key [key ...] arg [arg ...]

lua内置函数

redis.call和redis.pcall

两者非常相似,区别在于:

若 Redis 命令执行错误,redis.call() 将错误抛出(即 EVAL & EVALSHA 执行出错);

redis.pcall() 将错误内容返回。

通过文件执行脚本

通常情况下我们都是把lua script放到一个lua文件中,然后执行这个lua脚本,这种模式,key和value用一个逗号隔开就好了,

redis-cli --eval script  key1 key2 , arg1 age2

伪客户端

因为执行redis命令必须有相应的客户端状态,为了执行lua脚本中的redis命令,redis服务器专门为lua环境创建了一个伪客户端,并且用这个伪客户端负责处理lua脚本中的包含的所有redis命令

  1. lua环境将redis.call或者redis。pcall函数想要执行的命令传给伪客户端
  2. 伪客户端将想要执行的命令传给命令执行器
  3. 命令执行器执行伪客户端传给它的命令,并返回结果
  4. 伪客户端接受结果,并且返回给lua环境
  5. lua环境将结果返回给call或者pcall函数
  6. 函数返回值信息

eval的执行

  1. 根据客户端给定的lua脚本,在lua环境中定义一个lua函数
  2. 将客户端给定的脚本保存到lua_scripts字典
  3. 执行刚刚定义的函数
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值