使用 Lua 脚本中的 eval 命令进行本地变量赋值。

我是一个 Lua 脚本的初学者。我尝试在 Redis 客户端中执行下面的命令:

eval "print('hello world')" 0

它能够正常工作,并返回:

hello
(nil)

首先,我不明白为什么 nil 总是返回/被打印出来?是因为 Lua 数据类型和 Redis 数据类型之间的互相转换会返回 nil 吗?

接下来,我尝试使用 if 语句并执行以下脚本:

eval "local t = 0; if t == 0 then print('hello'); end" 0 0

上述命令按预期打印:

hello
(nil)

但是,当我尝试使用以下代码将参数分配给本地变量时:

eval "local t = ARGV[1]; if t == 0 then print('hello'); end" 0 0

输出仅为:

(nil)

所以,有人能否向我解释如何进行将外部参数分配给本地变量?

点赞
用户1150918
用户1150918

根据[Redis EVAL documentation] (http://redis.io/commands/EVAL) ,使用eval()执行的chunk访问全局变量已被禁用。虽然没有提到,但我怀疑访问local变量甚至更严重可能泄露信息。因此,应按照官方文档使用Redis keys。或者,当然,重复使用返回值。

来自eval() 文档的相关部分:

全局变量保护

Redis脚本不允许创建全局变量,以避免将数据泄漏到Lua状态中。如果脚本需要在调用之间维护状态(一种非常罕见的需求),则应改用Redis密钥。

刚刚意识到,问题的正文与问题的标题不符,所以重新开始...

正确的eval()用法(来自Redis文档):

EVAL的第一个参数是Lua 5.1脚本。脚本不需要定义Lua函数(也不应该)。它只是一个Lua程序,在Redis服务器的上下文中运行。

EVAL的第二个参数是随脚本后面(从第三个参数开始)出现的参数数量,它表示Redis键名。这些参数可以通过Lua使用KEYS全局变量以形式化的基于一的数组形式来访问(因此KEYS[1],KEYS[2]...)。

所有其他参数不应表示键名,可以通过ARGV全局变量由Lua访问,非常类似于键的情况(因此ARGV[1],ARGV[2]...)。

在您的示例中,将参数的数量设置为0,因此未传递任何内容到您的Lua脚本。快速修复:

eval "local t = ARGV[1]; if t == 0 then print('hello'); end" 1 0

不确定是否是nil,但可能仅因为您提供的Lua块未返回任何内容。

2013-12-19 12:58:34
用户1244588
用户1244588

Redis 的 eval 命令仅仅是将输入拆分为标记,因此你的参数 0 是一个 string,而不是一个 number

然而,在 Lua 中,比较 0 == "0" 是错误的,所以你需要更改为以下其中一种变体:

eval "local t = ARGV[1]; if t == '0' then print('hello'); end" 0 0
eval "local t = ARGV[1]; if tonumber(t) == 0 then print('hello'); end" 0 0

注意: 由于 Kamiccolo 进行了提及,需要注意的是,在 Lua 的 eval 中,你永远不能访问来自于 eval 之外的 local 变量,因为代码总是在 全局 上下文中执行!

2013-12-20 14:05:45