Lua中loadfile传参为何无法为play.lua填充arg[1]?
问题说明
我有一个play.lua脚本,它通过命令行传入的文件名参数读取文件每行的音符并播放。现在写了jukebox.lua脚本,想根据输入给play.lua传不同参数,但用loadfile时全局参数表arg没法保留传入的参数。
play.lua报错代码片段
local name = "file " .. arg[1] for line in io.lines(arg[1]) do --[[音符播放代码]]-- print(".") end
首次尝试(报错)
jukebox.lua代码:
assert(loadfile("play.lua"))("file1")
运行后play.lua里arg[1]为nil,触发报错。
第二次尝试(无报错但无效果)
jukebox.lua代码:
arg[1] = "file1" assert(loadfile("play.lua"))()
运行lua jukebox.lua时没有播放内容也无打印输出,但直接执行lua play.lua file1就能正常播放并为每行打印"."。试过dofile和require,结果类似。
核心问题
脚本中使用assert(loadfile("play.lua"))("file1")和控制台执行lua play.lua file1效果是否一致?
补充测试脚本
play.lua
local name = "file " .. arg[1] for line in io.lines(arg[1]) do print(".") end
jukebox.lua
arg[1] = "file1" assert(loadfile("play.lua"))()
解答
两者效果完全不一致:
- 控制台执行
lua play.lua file1时,Lua解释器会自动初始化全局arg表,把file1存入arg[1],同时arg还包含脚本路径、解释器路径等完整的启动参数信息。 - 用
assert(loadfile("play.lua"))("file1")时,传入的"file1"是作为函数参数传递给loadfile返回的匿名函数的,不会自动填充到全局arg表中。play.lua依旧读取全局arg,自然拿不到值。
- 控制台执行
两种修复方案:
方案一:修改
play.lua,改用函数参数接收输入,不再依赖全局arg:-- play.lua local filename = ... -- 接收调用时传入的参数 local name = "file " .. filename for line in io.lines(filename) do print(".") -- 音符播放代码 end对应的jukebox.lua调用方式:
assert(loadfile("play.lua"))("file1")方案二:不修改
play.lua,完整模拟Lua解释器启动时的arg表结构:-- jukebox.lua arg = { [-1] = arg[-1], -- 保留原解释器路径 [0] = "play.lua", -- 模拟脚本名字段 [1] = "file1" } assert(loadfile("play.lua"))()之前仅赋值
arg[1]无效,是因为arg表的结构和解释器启动时的完整结构不符,导致io.lines等依赖arg完整信息的逻辑异常。
内容的提问来源于stack exchange,提问作者Luc Riffault
相关产品推荐
相关产品推荐

