物联网学习---番外篇Lua脚本编程扫盲
Posted 玖零大壮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了物联网学习---番外篇Lua脚本编程扫盲相关的知识,希望对你有一定的参考价值。
在后面的物联网教程中,我们很快就会接触到Lua这个脚本语言,那么本篇内容结合后续的一些需要的开发点,针对Lua零基础的读者写一篇入门扫盲文章。
01
Lua 介 绍
Lua是一个小巧的脚本语言,其目标是成为一个很容易嵌入其它语言中使用的语言。同样的,基于Lua的定位,它并不适合作为开发独立应用程序的语言。
它有以下特性:
轻量级:Lua语言的官方版本只包括一个精简的核心和最基本的库。这使得Lua体积小、启动速度快,从而适合嵌入在别的程序里,5.0.2版的Lua的内核小于120KB。
可扩展:Lua并不象其它许多"大而全"的语言那样,包括很多功能,比如网络通讯、图形界面等。但是Lua提供了非常易于使用的扩展接口和机制:由宿主语言(通常是C或C++)提供这些功能,Lua可以使用它们,就像是本来就内置的功能一样。
其它特性:Lua还具有其它一些特性:同时支持面向过程(procedure-oriented)编程和函数式编程(functional programming);自动内存管理;只提供了一种通用类型的表(table),用它可以实现数组,哈希表,集合,对象;语言内置模式匹配等。
___来源 百度百科
在这里我首先推荐一个可以在线运行Lua的网站,我们接下来的实验都在这个网站上在线运行。
https://www.runoob.com/try/runcode.php?filename=datatype1&type=lua
02
注释 及 函数
Lua的函数是按照下面格式定义的:
function 函数名(参数1, 参数2, ...)
函数体
end
Lua的注释有以下三种:
单行注释:两个减号是单行注释
--
多行注释
--[[
多行注释
多行注释
--]]
运行以下程序:
--测试函数定义
function sayHello()
print("公众号:玖零大壮")
print("print是Lua自带打印函数")
end
--字符串连接符号演示
function fun1(para1)
print("两个逗号连接两边的字符串"..para1)
print("连接符1" .. "连接符2".. "连接符3")
end
--多参数传递演示
function fun2(para1, para2)
print("print中逗号用法")
print(para1, para2)
end
sayHello(); --语句后面可带分号,也可不带
fun1("Hello")
fun2("数字",1);
上面额外演示了以下内容:
..用来连接字符串,并且连接符可以与两边的字符串间有空格
语句后面可以有分号,也可以无分号。和Matlab挺像的
print()是lua自带的打印输出函数,不同参数之间逗号分隔
03
变 量 修 饰 符
在默认情况下,变量总是认为是全局的,全局变量不需要声明,给一个变量赋值后即创建了这个全局变量。
local是lua特有的关键词,表示声明一个局部变量。
local a = "我是局部变量a"
b = "我是全局变量b"
function fun1()
a = "我是函数内声明的全局变量a"
end
function fun2()
local b = "我是函数内局部变量b"
end
print(a)
print(b)
fun1()
fun2()
print(a)
print(b)
上面演示了全局变量和局部变量的用法,记住local这个关键词修饰符就行了。
访问一个没有初始化的全局变量也不会出错,只不过得到的结果是:nil
如果你想删除一个全局变量,只需要将变量赋值为nil。(nil相当于其它语言的null)
print(a) --因为a没有声明,所以是nil
a = 1
local b = 1
print("a+b=" .. a+b)
a=nil --给变量赋值为nil就是删除该变量
b=nil
print(a,b)
再看下面的实验
你看,全局变量就是这么豪横!!
04
数 据 类 型
Lua 是动态类型语言,变量不要类型定义,只需要为变量赋值。值可以存储在变量中,作为参数传递或结果返回。
Lua 中有 8 个基本类型分别为:nil、boolean、number、string、userdata、function、thread 和 table。
表 lua数据类型概览 来源runoob
来做个实验
print(type(nil)) -- nil
print(type(true)) -- boolean
print(type(10.4*3)) -- number
print(type("Hello world")) -- string
print(type(print)) -- function
print(type(type)) -- function
print(type(type(X))) -- string
注意一个有意思的地方:
Lua 把 false 和 nil 看作是 false,其他的都为 true,数字 0 也是 true
关于数据类型table,得单独在下面的小章节解释。
05
字 符 串 操 作
字符串或串(String)是由数字、字母、下划线组成的一串字符。
Lua 语言中字符串可以使用以下三种方式来表示:
单引号间的一串字符
双引号间的一串字符
[[和]]间的一串字符
string1 = "Hello"
--下面有个转义字符
print(""字符串 1 是"",string1)
string2 = 'IOT'
print("字符串 2 是",string2)
string3 = [[Study]]
print("字符串 3 是",string3)
Lua也自带了一些字符串的操作函数,这里我就介绍我后面的教程中所需要的知识点:字符串格式化和字符串分割。
字符串格式化函数string.format()
字符串分割:
lua中没有C语言那样直接用来分割的split函数,但是我们可以自定义,下面是我从网上直接找来的代码。
--------------------------------------------------------------
-- 按照字符分割字符串 --
-- @param str 字符串 --
-- @param delimiter 分割字符 --
-- @return 返回字符串数组 --
-- @example local arr = split("123#321","#") --
-- print(arr[1])
-- print(arr[2])
-- 来源:https://www.runoob.com/note/28521
--------------------------------------------------------------
function split(str,delimiter)
local dLen = string.len(delimiter)
local newDeli = ''
for i=1,dLen,1 do
newDeli = newDeli .. "["..string.sub(delimiter,i,i).."]"
end
local locaStart,locaEnd = string.find(str,newDeli)
local arr = {}
local n = 1
while locaStart ~= nil
do
if locaStart>0 then
arr[n] = string.sub(str,1,locaStart-1)
n = n + 1
end
str = string.sub(str,locaEnd+1,string.len(str))
locaStart,locaEnd = string.find(str,newDeli)
end
if str ~= nil then
arr[n] = str
end
return arr
end
我们接下来做个实验:
这里注意一点:
在lua中的“数组”(其实lua没有真正的数组概念)的索引值是从1开始的。
(题外话:我为什么需要上面这个字符串分割的功能呢?因为我在后面使用NB模组传数据的时候,为了节省SIM物联卡的流量,通常透传纯数据)
假如说我们想在lua中赋值一个json格式的字符串,比如下面的格式:
[
{
"v":{
"lat": 1.2,
"lon": 2.3
},
"i":"location",
"a": 0
}
]
我们应该怎么做呢?我们其实可以按照下面的方法进行赋值:
local lat = 1.2
local lon = 2.3
local name = "location"
local json_str = string.format('[{"v":{"lat":%f,"lon":%f},"i":"%s","a":0}]', lat, lon, name)
print("----- 第一种表现形式 -----")
print(json_str)
local format_pattern = [[
[
{
"v":{
"lat": %f,
"lon": %f
},
"i": "%s",
"a": 0
}
]
]]
json_str = string.format(format_pattern, lat, lon, name)
print("----- 第二种表现形式 -----")
print(json_str)
运行结果:
这个实验是重点,我后面讲解OneNET TCP透传的时候会用到。
其它的字符串操作函数可以暂时忽略,后面不会用到。
06
流 程 控 制
关于流程控制循环语句、条件语句这一块的内容,我不讲的很仔细,至少我在后面演示的时候基本不用,有兴趣的可以去这里学习一下:
https://www.runoob.com/lua/lua-loops.html
https://www.runoob.com/lua/lua-decision-making.html
这里简单演示一下使用:
local lat = 1.2
-- if else用法
if type(lat) ~= "number" then
print("lat数据类型不是number")
else
print("lat数据类型是number")
end
-- 数值for循环
for i=1,3,1 do
print(i)
end
-- 迭代器用法
local t = {"hello", "iot"}
for i,v in ipairs(t) do
print(i,v)
end
07
table 表
table 是 Lua 的一种数据结构用来帮助我们创建不同的数据类型,如:数组、字典等。
table在Lua中是比较重要的一个知识点,建议去这个连接仔细看一下:
https://www.runoob.com/lua/lua-tables.html
下面我简单的做个实验,体会一下其用法。为了方便调试,我贴一个从网络上找到可以输出table内容的print函数,如下:
-- 输出table表内容
-- 来源:https://www.cnblogs.com/leezj/p/4230271.html
function print_r ( t )
local print_r_cache={}
local function sub_print_r(t,indent)
if (print_r_cache[tostring(t)]) then
print(indent.."*"..tostring(t))
else
print_r_cache[tostring(t)]=true
if (type(t)=="table") then
for pos,val in pairs(t) do
if (type(val)=="table") then
print(indent.."["..pos.."] => "..tostring(t).." {")
sub_print_r(val,indent..string.rep(" ",string.len(pos)+8))
print(indent..string.rep(" ",string.len(pos)+6).."}")
elseif (type(val)=="string") then
print(indent.."["..pos..'] => "'..val..'"')
else
print(indent.."["..pos.."] => "..tostring(val))
end
end
else
print(indent..tostring(t))
end
end
end
if (type(t)=="table") then
print(tostring(t).." {")
sub_print_r(t," ")
print("}")
else
sub_print_r(t," ")
end
print()
end
如下测试代码:
local t ={} -- 初始化表
t[1] = "Hello" -- 赋值
t.h = "IOT"
t.a = {"hello", "iot"}
print_r(t)
t = nil --移除引用,Lua垃圾回收会释放内存
仔细揣摩一下,新增值时,索引的方法。
08
面 向 对 象
面向对象编程(Object Oriented Programming,OOP)是一种非常流行的计算机编程架构,Lua同样支持面向对象的编程方式,支持继承、多态、抽象。
我们知道,对象由属性和方法组成。Lua中最基本的结构是table,所以需要用table来描述对象的属性。
Lua 中的 function 可以用来表示方法。那么Lua中的类可以通过 table + function 模拟出来。
请看下面的实验:
-- 初始化
Area = {width = 0, height=0}
-- 方法1
function Area:SetPara(width, height)
self.width = width;
self.height = height;
end
-- 方法2
function Area:Squrare()
return self.width * self.height;
end
print(Area.width , Area.height)
Area:SetPara(10,20)
print(Area.width , Area.height)
print("面积=" .. Area:Squrare())
看一下这个用法,大致的知道怎么回事儿就行。
讲话了,我写到这里就完事儿了,手打字都打酸了。有了以上这些,足以应对后面的实验了。
点击下方原文链接查看相关文章
以上是关于物联网学习---番外篇Lua脚本编程扫盲的主要内容,如果未能解决你的问题,请参考以下文章