最近做仪器软件开发,需要一种脚本语言做对外接口,Lua的解析器小巧、语法简单、方便和C绑定,所以选择了Lua,记录学习笔记如下:
一、变量与类型
变量声明与赋值
- 直接赋值即可声明变量,无需显式声明类型
- 使用
local声明局部变量,仅在当前作用域(如文件、函数、代码块)内有效 - 未声明的变量默认值为
nil - 支持同时给多个变量赋值,例如:
x, y, z = 1, 2, 3
Number(数值类型)
-
Lua 中所有数值均为
number类型(内部可能为整数或浮点数,自动转换) -
支持多种表示方式:
luaa = 42 -- 十进制 b = 0xFF -- 十六进制 c = 3.14e-2 -- 科学计数法 -
支持常见算术运算(
+、-、*、/、%)及位运算(>>、<<、&、|、~)
String(字符串类型)
-
用双引号
"或单引号'表示,如:"hello"或'world' -
使用
[[ ... ]]包裹的字符串不解析转义字符,适合多行文本 -
字符串连接使用
..运算符 -
常用字符串函数:
luas = "Lua" print(#s) -- 获取长度:3 print(string.format("%s %d", "Lua", 5)) -- 格式化输出 print(string.sub(s, 2, 3)) -- 取子串:"ua" print(string.char(65, 66)) -- ASCII 转字符:"AB" print(string.byte("A")) -- 字符转 ASCII:65
类型转换
-
tostring(number):将数字转为字符串 -
tonumber(string):将字符串转为数字,失败则返回nilluaprint(tostring(123)) -- "123" print(tonumber("456")) -- 456 print(tonumber("abc")) -- nil
二、Table(表)
基本特性
- Table 是 Lua 中唯一的数据结构,可当作数组、字典、对象使用
- 可存储任意类型值(数字、字符串、函数、甚至其他表)
- 数字下标从 1 开始
- 使用
#table获取数组部分的长度(不包含字符串键值)
数组式用法
lua
arr = {1, "hello", {x=1}, function() print("func") end}
table.insert(arr, "new") -- 尾部插入
table.remove(arr, 2) -- 移除第2个元素
print(#arr) -- 获取长度
print(arr[1]) -- 访问第一个元素
字典式用法(字符串下标)
lua
dict = {
name = "Lua",
version = 5.4,
say = function() print("Hi") end
}
dict["extra"] = "some value" -- 等价于 dict.extra = "some value"
print(dict.name) -- "Lua"
dict.say() -- 调用函数,输出 "Hi"
遍历 Table
lua
for k, v in pairs(dict) do
print(k, v)
end
-- 仅遍历数组部分(连续数字下标)
for i, v in ipairs(arr) do
print(i, v)
end
三、Function(函数)
定义函数
两种等价方式:
lua
-- 方式一:直接定义
function add(a, b)
return a + b
end
-- 方式二:匿名函数赋值
add = function(a, b)
return a + b
end
函数特性
- 可以返回多个值
- 调用时传入参数少于形参,缺少的参数为
nil - 调用时传入参数多于形参,多余参数被忽略
- 无显式
return时,返回nil
lua
function multiReturn()
return 1, "two", true
end
local a, b, c = multiReturn()
print(a, b, c) -- 1 two true
四、布尔类型与逻辑运算
布尔值
- 只有
true和false两个值 - 注意:在条件判断中,只有
false和nil视为"假",0 和空字符串均为真
逻辑运算符
and:逻辑与or:逻辑或not:逻辑非- 不等于使用
~=表示
三元运算模拟
Lua 中没有 ? : 三元运算符,但可用 and 和 or 模拟:
lua
local result = (condition) and "yes" or "no"
-- 相当于 condition ? "yes" : "no"
示例:
lua
print(0 and "yes" or "no") -- "yes"(因为 0 为真)
print(nil and "yes" or "no") -- "no"
五、流程控制
条件判断
lua
if score >= 90 then
print("优秀")
elseif score >= 60 then
print("及格")
else
print("不及格")
end
循环结构
for 循环
lua
-- 数值 for:起始值, 结束值, 步长(默认为 1)
for i = 1, 10 do
print(i)
end
for i = 10, 1, -1 do
print(i)
end
-- 注意:循环变量 i 在循环内部不可被修改
while 循环
lua
local i = 1
while i <= 5 do
print(i)
i = i + 1 -- Lua 没有 i++ 或 i += 1 语法
end
repeat...until(类似 do-while)
lua
local i = 1
repeat
print(i)
i = i + 1
until i > 5
六、全局表 _G
_G是 Lua 的全局环境表,所有全局变量和函数都存储在其中- 可通过
_G["变量名"]访问全局变量 - 预定义函数(如
print、table.insert)也存放在_G中
lua
a = 10
print(_G["a"]) -- 10
print(_G["table"]["insert"]) -- function: 地址
七、字符串与字节操作
字符串与字节转换
lua
local s = string.char(0x33, 0x34, 0x35) -- 将 ASCII 码转为字符串 "345"
print(string.byte(s, 1)) -- 取第一个字符的 ASCII 码:51(0x33)
print(string.format("0x%02X", string.byte(s, 1))) -- 格式化为十六进制:0x33
字符串长度
- 使用
#获取字符串字节数(对于 ASCII 字符串即字符数) - 对于多字节字符(如 UTF-8),需使用特定库获取正确字符数
lua
print(#"hello") -- 5
print(#"中文") -- 6(UTF-8 下每个中文占 3 字节)
八、注意事项与小技巧
- 数组下标从 1 开始:这是 Lua 的传统,许多内置函数(如
table.insert)都基于此。 - 小心全局变量:尽量使用
local避免污染全局空间。 - 类型自动转换:字符串与数字在算术运算时会尝试自动转换,但显式转换更安全。
- table 长度陷阱:
#table只对连续数字下标的数组部分有效,对字典部分无效。 - 多重赋值:可用于交换变量值,如
x, y = y, x。 - 函数多返回值:若函数调用不在赋值语句最后,则只返回第一个值。
一个月前bellard大佬开源了用于嵌入式平台的MicroQuickJS引擎,本人完美错过,感兴趣的同学可以研究下,毕竟"所有能用JavaScript解决的问题,最后都会用JavaScript去解决"。