Lua使用方式介紹

背景

Lua是C語言開發的腳本語言,設計的目的是為了嵌入到程序中,因此被設計得輕量小巧。Nginx配置中可以直接嵌入Lua 代碼或引入Lua 文件,Redis支持運行Lua語句和腳本,Wireshark中使用Lua腳本自定義協議。
本文用于收集常用的語法和API,用作記事本而不會過多深入,內容后續會不斷更新。

1.Lua數據類型和變量

Lua有8種基本類型:
[1] boolean布爾: true和false;在Lua中,僅false和nil表示假;其他為真,這與部分語言中默認值為假不同;
[2] number數值: 整數和浮點數;
[3] string字符串:由單引號或者雙引號包含的部分;
[4] function函數: 由C語言或者LUA定義的函數;
[5] table表:靈活的數據結構,可以用作數組、哈希表、集合等多種數據類型;
[6] nil: 空對象、空值、或者未聲明變量的值;
[7] userdata: C語言數據結構,lua不能直接訪問和操作這些數據,只能通過C語言的API來操作;
[8] thread類型: 在Lua中表示一個協程,用于實現并發。
lua作為動態語言,聲明變量時無需指定變量的類型,賦值決定類型,之后可通過type()函數查看變量的類型.

var1 = true
var2 = 100
var3 = 100.01
var4 = "test"
var5 = function(a)print(a)
endvar6 = {}
var7 = nilprint("type var1 is:" .. type(var1))
print("type var2 is:" .. type(var2))
print("type var3 is:" .. type(var3))
print("type var4 is:" .. type(var4))
print("type var5 is:" .. type(var5))
print("type var6 is:" .. type(var6))
print("type var7 is:" .. type(var7))

運行結果如下:

type var1 is:booleantype var2 is:numbertype var3 is:numbertype var4 is:stringtype var5 is:functiontype var6 is:tabletype var7 is:nil

變量有全局變量和局部變量之分,全局變量全局有效,而局部變量(在聲明時添加local)僅在所在語句塊內有效:

-- a為全局變量
>a=0-- b為局部變量
>local b='ss'

變量之間的比較,使用 == 表示相等, ~=表示不等:

>local a=1>print(a==1)
true>print(a~=1)
false

數值方面的大小比較以及基本運算與Java相同。

2.邏輯運算與條件判斷

使用 and or not 表示與或非:

>local b="ss">print(b=="s" or b=="ss")
true

Lua的if語法為:

if 條件 then邏輯
endif 條件 then邏輯1
else 邏輯2
endif 條件1 then邏輯1
elseif 條件2 then邏輯2
else邏輯3
end

3.字符串

Lua中定義字符串時,可用單引號或者雙引號。

local str = "hello world"

[1] 長度

-- string.len(arg)返回字符串長度
>local str = "hello world"
>print(string.len(str))
11

[2] 拼接

--使用..進行字符串拼接
>local str = "hello world"
>str_print = "str is : " .. str .. "."
>print(str_print)str is : hello world.

[3] 大小寫轉換

--全部轉為大寫string.upper(arg):
--全部轉為小寫string.lower(arg):>local str = "hello"
>strUpper = string.upper(str)
>print("strUpper: " .. strUpper)
strUpper: HELLO>strLower = string.lower(strUpper)
>print("strLower: " .. strLower)
strUpper: HELLO

[4] 是否包含

--  string.find(str, "test") 返回"test"在str中的其實索引,如果不存在,返回nil
>str = "test1"
>find_result = string.find(str, "test")
>print(find_result)
1--可通過是否等于nil來判斷是否包含
str = "test1"
if string.find(str, "test") ~= nil thenprint("yes")
elseprint("no")
end

[5] 截取

-- string.sub(str, i [, j]) 將str從i截取到j位,如果省略j表示截取到字符串尾部
>local str = "hello world"
>local str_sub1=string.sub(str, 1)
>print("str_sub1 is " .. str_sub1)
str_sub1 is hello world>local str_sub15=string.sub(str,1,5)
>print("str_sub15 is " .. str_sub15)
str_sub15 is hello

使用string.sub(str, i [, j]方法時注意Lua中位置索引從1開始而不是0開始,j是未知索引而不是長度,i和j都為閉區間。
[6] 刪除空格

function trim(inputString)return string.gsub(inputString, "^%s*(.-)%s*$", "%1")
end-- 示例用法:
local myString = "   Hello, World!   "
local trimmedString = trim(myString)  -- 返回 "Hello, World!"
print(trimmedString)  -- 輸出: Hello, World!

[7] 替換

--string.gsub(str, "test", "hello")
-- 將str字符串中的test改成hello
>local str = "test1test2test"
>local result = string.gsub(str, "test", "hello")
>print(result)
hello1hello2hello

4.table類型

table可以被當做數組或者哈希表使用。
數組:

-- 1.聲明方式:使用大括號
local myArray = {"a", "b", "c"}--2.獲取長度:通過#數組名,獲取數組長度
>print(#myArray)
3--3.添加元素
--通過table.insert(myArray, e) 添加元素
>local emptyTable = {}
>table.insert(emptyTable,"x")
>table.insert(emptyTable,"y")
>print(#emptyTable)
2
--也可以直接通過下標獲取、設置、添加元素
>emptyTable[1]="x1"
>print(emptyTable[1])
x1--4.刪除元素
table.remove(myArray) -- 刪除myArray數組最后一個元素
table.remove(myArray, i) --刪除myArray數組的第i個元素--5.遍歷
local myArray = {"a", "b", "c"}
for k, v in pairs(myArray) doprint(v) -- v為數組元素 a b c
end

其中local emptyTable = {}聲明了一個數組,執行table.insert(emptyTable,"x")向數組中添加了一個元素"x", 等價于emptyTable[1] ="x".

其他語言中,一般下標是下標,不會認為是整數類型的Key; 在Lua語言中,可以認為emptyTable[1] ="x"是向哈希表emptyTable中添加了一個鍵值對,鍵是1,值是x.

哈希表:

--1.聲明哈希表,使用{}
local myHash = {name = "sy", role = "role_a"}--2.添加元素
myHash.age=18--3.刪除元素
myHash.age = nil--4.遍歷
local myHash = {name = "sy", role = "role_a"}
for k, v in pairs(myHash) doprint(k,v) -- k為鍵,v為值
end

注意:當哈希表中的鍵的值被設置為nil時,Lua在下一次垃圾回收時會清理這個鍵值對。

5.循環邏輯

while循環

while condition do-- 這里是循環體,只要condition為真,就會不斷執行這里的代碼
end--案例如下:
local i = 1
while i <= 5 doprint(i)i = i + 1
end

for循環
前面介紹table時已經用過for循環,除了遍歷數組和哈希表外,還可以指定循環次數:

-- initial 是起始值,limit 是結束值,step 是步長(步長可以是正數也可以是負數,默認為 1)
for var = initial, limit, step do-- 這里是循環體
end--案例如下:
local myArray = {"a", "b", "c"}
for i = 1, #myArray doprint(myArray[i])
end

注意:Lua有goto,但是沒有continue和break.

6.函數

和變量相同,Lua定義函數時可以通過local指定作用域: 全局或者局部。
使用關鍵字function聲明函數,模板如下所示:

function myFunName()--函數邏輯
end

(1) 函數入參
可以在聲明時添加參數

function myFunName(arg1,arg2,agr3)--函數邏輯
end--案例如下:
function printArgsFunc(arg1, arg2, arg3)print("args is: " .. arg1 .. arg2 .. arg3)
end
>printArgsFunc('a','b','c')
args is: abc

(2) 返回值
當函數需要返回數據時,通過添加return語句返回;和python相似,返回多個數據時,使用逗號分隔。

function myFunName(arg1,arg2,agr3)--函數邏輯return arg1,arg2,agr3
end--案例如下:
function getArgsFunc(arg1, arg2, arg3)return arg1, arg2, arg3
end
>local result1, result2, result3, result4 =  getArgsFunc("a","b","c")
>print("result1 is: " .. result1)
>print("result2 is: " .. result2)
>print("result3 is: " .. result3)
>print(result4)result1 is: a
result2 is: b
result3 is: c
nil

由于Lua是腳本語言,因此需要先定義再調用,調用方式與python類似。

7.對象

Lua本身不具備面向對象的語法,但是可以使用面向對象的思想通過表數據結構模擬出對象。在介紹對象前,有必要提前說明一下元表的概念和一個Lua語法糖。

7.1 元表

元表的概念是定義原始值在特定下的行為。概念比較抽象和難懂,理解元表需要結合使用案例進行。
關聯方式
元表是一種特殊的表,每個表可以關聯一個元表,通過setmetatable(表,元表)方法關聯:

t = {}
mt = {}
-- 表t關聯mt元表
setmetatable(t,mt)

__index屬性
當從表t中查詢不存在的key時,轉向元表mt的__index屬性。有兩種情況:
[1] __index為表:直接從__index表中根據key取值

>t = {}
>mt = { __index={ a=1, b=2 }}
>setmetatable(t,mt)
>print(t.a)
1
>print(t.c)
nil

分析: mt為t的元表,訪問t.a和t.c時,因為t表中不存在a和c屬性,請求會轉向元表的__index屬性,
此時__index屬性是元表且其中有a屬性—返回1,沒有c屬性—返回nil.

[2] __index為函數:將表t和key作為參數傳遞給__index函數

>t = {}
>mt = { __index=function(t, key)return "sy"end	
}
>setmetatable(t,mt)
>print(t.a)
sy
>print(t.c)
sy

分析: mt為t的元表,訪問t.a和t.c時,因為t表中不存在a和c屬性,請求會轉向元表的__index屬性,
此時__index為方法,將t和key傳遞給__index方法,該方法返回固定值“sy”, 因此t.a和t.c得到的結果均為"sy".

__newindex屬性
當向表t中添加新的key時,轉向元表mt的__newindex屬性。有兩種情況:
[1] __newindex為表:直接添加到__newindex表中根據key取值

>t = {}
>mt = { __newindex={}
}
>setmetatable(t,mt)
>t.a="aa"
>print(t.a)
nil
>print(mt.__newindex.a)
aa

分析:mt為t的元表,向t中添加元素時,轉向元表mt的__newindex屬性,此時該屬性為表,將元素添加到__newindex中。

[2] __newindex為函數:將表t和key作為參數傳遞給__newindex函數

>t = {}
>mt = { __newindex=function(t,k,v)rawset(t,k,v)end
}
>setmetatable(t, mt)
>t.a="aa"
>print(t.a)
aa

分析:mt為t的元表,向t中添加元素時,轉向元表mt的__newindex屬性,此時該屬性為函數,將t,k,v作為參數傳遞給__newindex函數;其中rawset(t,k,v)函數將 k,v設置到t表中。

其他屬性:
__add用于重載表的操作符(+),類似的還有減法、乘除法等。

7.2 語法糖

Lua調用表中的方法時,如果需要將自己作為參數傳遞,可以使用冒號調用方法,從而省略第一個參數,如下所示:

table.func(table,arg1,argn)
-- 等價于
table:func(arg1,argn)

以下通過一個案例進行說明。

t = {name="sy",getName = function(t)return t.nameend
}
print(t.getName(t))

上述代碼定義了一個表t, 內部定義了一個name屬性和一個getName方法:getName方法接受一個表參數,并返回這個表的name屬性,此時獲取t的name屬性需要傳參t。
上面的方法可以修改一下,將t用self修改一下:

t = {name="sy",getName = function(self)return self.nameend
}
print(t.getName(t))
-- 等價于print(t:getName())

如此,使用getName方法的人,不會為getName傳遞其他表參數,認為這是特定為t表定制的方法。
print(t.getName(t))可以使用語法糖print(t:getName())代替。t:getName()給人一種調用t對象的getName方法的感覺。

7.3 對象

定義一個Person表,只有一個name屬性和一個getName方法:

>Person={ name = "sy",getName = function(self)return self.name;end
}>print(Person:getName())
sy

為Person添加一個new方法:

function Person:new()local t = {}setmetatable(t,{__index=self})return t
end

通過Person的new方法可以創建一個新Person表,此時存在3個表:Person表,匿名表,t表(新Person表):
new方法中聲明了一個t表并在函數調用結束時返回t表,即調用new方法最終得到的新Person表是t表;
{__index=self}定義了一個匿名表;通過setmetatable方法將匿名表設置為t表的元表;
而匿名表的__index屬性為self,即Person表;
此時,當獲取 t表中不存在的屬性或者方法時,會轉向元表的__index屬性,即Person表。
因此,可通過新Person表訪問Person表的屬性和方法:

>local p = Person:new()
>print(p:getName())
sy

進一步地,可以為new方法添加一個元表參數,該元表將繼承Person表的屬性:

function Person:new(tableArg)local t = tableArg or {}setmetatable(t,{__index=self})return t
end

此時, 通過new方法得到的元表不僅擁有Person表的屬性,還保留tableArg表自身的屬性:

local Student = { class = 4 }
>local stuInstance = Person:new(Student)
>print(stuInstance.class)
4
>print(stuInstance:getName())
sy

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/20939.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/20939.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/20939.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

JMeter源碼解析之SplashScreen.java

JMeter源碼解析之SplashScreen.java完結 SplashScreen.java主要作用 JMeter GUI啟動加載界面。 文件路徑 路徑地址&#xff1a;…\apache-jmeter-5.1\src\core\org\apache\jmeter\SplashScreen.java 關于SplashScreen內容中的代碼解析 package org.apache.jmeter;import …

隊列——一種操作受限的線性表

隊列 隊列&#xff08;Queue&#xff09;簡稱隊&#xff0c;也是一種操作受限的線性表&#xff0c;只允許在表的一端進行插入&#xff0c;而在表的另一端進行刪除。向隊列中插入元素稱為入隊或進隊&#xff0c;刪除元素稱為出隊或離隊。隊列中的元素是先進先出&#xff08;Fir…

大聰明教你學Java | 深入淺出聊 Stream.parallel()

前言 &#x1f34a;作者簡介&#xff1a; 不肯過江東丶&#xff0c;一個來自二線城市的程序員&#xff0c;致力于用“猥瑣”辦法解決繁瑣問題&#xff0c;讓復雜的問題變得通俗易懂。 &#x1f34a;支持作者&#xff1a; 點贊&#x1f44d;、關注&#x1f496;、留言&#x1f4…

MySQL學習——選項文件的使用

MySQL 的許多程序都可以從選項文件&#xff08;有時也被稱為配置文件&#xff09;中讀取啟動選項。選項文件提供了一種方便的方式來指定常用的選項&#xff0c;這樣你就不必每次運行程序時都在命令行上輸入這些選項。 要確定一個程序是否讀取選項文件&#xff0c;你可以使用 -…

man命令的作用

man命令是Linux操作系統中一個非常實用的命令&#xff0c;它用于查看命令的手冊頁面&#xff0c;幫助用戶了解特定命令的用法、選項和參數。這不僅對新用戶在學習如何使用新命令時很有幫助&#xff0c;也方便了經驗豐富的用戶快速查找命令的詳細信息。以下是具體介紹&#xff1…

[論文精讀]Supervised Community Detection with Line Graph Neural Networks

論文網址:[1705.08415] Supervised Community Detection with Line Graph Neural Networks (arxiv.org) 英文是純手打的!論文原文的summarizing and paraphrasing。可能會出現難以避免的拼寫錯誤和語法錯誤,若有發現歡迎評論指正!文章偏向于筆記,謹慎食用 ?內涵大量可視…

高速模擬信號鏈的設計學習

目錄 概述&#xff1a; 定義&#xff1a; 斷開&#xff1a; 鏈路設計&#xff1a; 結論&#xff1a; 概述&#xff1a; 由于對共模參數及其與設備之間的關聯缺乏了解&#xff0c;客戶仍然會提出許多技術支持問題。ADC數據表指定了模擬輸入的共模電壓要求。關于這方面沒有太…

jenkins應用2

1.jenkins應用 1.jenkins構建的流程 1.使用git參數化構建&#xff0c;用標簽區分版本 2.git 拉取gitlab遠程倉庫代碼 3.maven打包項目 4.sonarqube經行代碼質量檢測 5.自定義制作鏡像發送到遠程倉庫harbor 6.在遠程服務器上拉取代碼啟動容器 這個是構建的整個過程和步驟…

C# 反射類Assembly 程序集(Assembly)用法

常見的兩種程序集&#xff1a; 可執行文件&#xff08;.exe文件&#xff09;和 類庫文件&#xff08;.dll文件&#xff09;。 在VS開發環境中&#xff0c;一個解決方案可以包含多個項目&#xff0c;而每個項目就是一個程序集。 他們之間是一種從屬關系&#xff0c;也就是說&…

java —— 匿名內部類與 Lambda 表達式

一、匿名內部類 匿名內部類是一種沒有名稱的類&#xff0c;多用于只使用一次的情況&#xff0c;本質上就是其所繼承的父類或接口的一個子類。 &#xff08;一&#xff09;繼承普通類的情況 public class Test{public void method(){System.out.println("通用方法"…

Python與Android連接:深入探索與實現

Python與Android連接&#xff1a;深入探索與實現 在現代移動應用開發領域&#xff0c;Python和Android的結合使用為開發者帶來了無限的可能性。這種跨平臺的組合不僅拓寬了開發者的視野&#xff0c;也極大地提升了應用的靈活性和可擴展性。本文將從四個方面、五個方面、六個方…

【NLP開發】Python實現聊天機器人(微信機器人)

&#x1f37a;NLP開發系列相關文章編寫如下&#x1f37a;&#xff1a;1&#x1f388;【小沐學NLP】Python實現詞云圖&#x1f388;2&#x1f388;【小沐學NLP】Python實現圖片文字識別&#x1f388;3&#x1f388;【小沐學NLP】Python實現中文、英文分詞&#x1f388;4&#x1…

轉讓北京電力施工總承包二級資質變更條件和流程

在電力工程領域&#xff0c;資質等級是企業能否參與競標、承接工程的重要標志之一。北京電力工程總包二級資質的轉讓&#xff0c;是指已經取得該資質的企業將其資質轉讓給需要的企業。這種轉讓是基于合作與共贏的原則&#xff0c;旨在推動電力工程行業健康、穩定發展&#xff0…

記錄使用自定義編輯器做試題識別功能

習慣了將解析寫在代碼注釋&#xff0c;這里就直接上代碼啦&#xff0c;里面用到的bxm-ui3組件庫是博主基于element-Plus做的&#xff0c;可以通過npm i bxm-ui3自行安裝使用 // 識別方法&#xff1a; // dom 當前識別數據所在區域, questionType 當前點擊編輯選擇的題目類型&a…

力扣刷題--LCR 135. 報數【簡單】

題目描述 實現一個十進制數字報數程序&#xff0c;請按照數字從小到大的順序返回一個整數數列&#xff0c;該數列從數字 1 開始&#xff0c;到最大的正整數 cnt 位數字結束。 示例 1: 輸入&#xff1a;cnt 2 輸出&#xff1a;[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,1…

codeblock怎么編程:從入門到精通的全面指南

codeblock怎么編程&#xff1a;從入門到精通的全面指南 在數字化時代&#xff0c;編程已成為一項不可或缺的技能。Code::Blocks作為一款流行的開源集成開發環境&#xff08;IDE&#xff09;&#xff0c;為初學者和有經驗的開發者提供了強大的編程支持。那么&#xff0c;codebl…

C是結構化編程語言嗎:深度剖析與多維度解讀

C是結構化編程語言嗎&#xff1a;深度剖析與多維度解讀 在編程語言的浩瀚海洋中&#xff0c;C語言以其獨特的魅力占據著重要的地位。那么&#xff0c;C語言是否可以被歸類為結構化編程語言呢&#xff1f;這是一個值得深入探討的問題。本文將從四個方面、五個方面、六個方面和七…

Qt | Qt 資源簡介(rcc、qmake)

1、資源系統是一種獨立于平臺的機制,用于在應用程序的可執行文件中存儲二進制文件(前面所討論的數據都存儲在外部設備中)。若應用程序始終需要一組特定的文件(比如圖標),則非常有用。 2、資源系統基于 qmake,rcc(Qt 的資源編譯器,用于把資源轉換為 C++代碼)和 QFile …

java—MyBatis框架

簡介 什么是 MyBatis&#xff1f; MyBatis 是一款優秀的持久層框架&#xff0c;它支持自定義 SQL、存儲過程以及高級映射。MyBatis 免除了幾乎所有的 JDBC 代碼以及設置參數和獲取結果集的工作。MyBatis 可以通過簡單的 XML 或注解來配置和映射原始類型、接口和 Java POJO&…

軟件公司為什么必須要使用低代碼系統?

在當今軟件行業全國比較內卷的大環境下&#xff0c;軟件公司面臨著前所未有的挑戰。為了在這個競爭激烈的市場中生存并脫穎而出&#xff0c;馳騁低代碼設計者認為&#xff0c;軟件公司必須要使用低代碼系統。以下是幾個關鍵的原因&#xff1a; 時代發展的必然選擇 低代碼系統是…