2

我有一个脚本

local fields = redis.call('hkeys', 'a:hash:full:of:stuff');
local retval = {};
for i, field in pairs(fields) do
    if((string.match(tostring(field),'ev')) ~= nil) then
        retval[i] = {field, (string.match(tostring(field),'ev') ~= nil) }
    end
end
return retval

此脚本返回一个空列表

当我将if语句更改为

if((string.match(tostring(field),'.')) ~= nil) then
    ...

我得到一个长长的清单,其中包括以下内容

...
...
60) 1) "applet:1:metric:viewelement:20130607"
    2) (nil)
61) 1) "applet:1:total_events:20130529"
    2) (integer) 1
...
...

如果我将 if 语句替换为

if(1)

我得到同样长的钥匙列表

我也试过使用string.find,它有类似的行为。

唯一看起来是一种模式的是,if如果匹配的字符串在字符串中出现多次,或者如果它出现在开头,则该语句将通过。我不能很确定,但它可能会有所帮助。

我正在使用以下命令运行此脚本

$ redis-cli eval "$(cat get_keys.lua)" 0
4

2 回答 2

2
  1. 你不需要做if((string.match(tostring(field),'ev')) ~= nil)。你可以这样做if(string.match(tostring(field),'ev'))
  2. 您的脚本失败的原因是 lua 不支持表中的 nil 键。如果你设置some_table[1], some_table[2],some_table[5]然后返回数组,它看起来会以 . 结尾some_table[2]。由于您仅在 if 语句通过时设置数组,因此如果它在 上失败retval[1],则不会返回数组的其余部分。

简单的解决方法是:

local fields = redis.call('hkeys', 'a:hash:full:of:stuff');
local retval = {};
for i, field in pairs(fields) do
    if(string.match(tostring(field),'ev')) then
        retval[i] = {field, (string.match(tostring(field),'ev') ~= nil) }
    else retval[i] = 'some_nil_value'
    end
end
return retval

我认为你也可以使用table default values,但我还没有玩过这些,所以不能在这里提供太多信息。

[编辑] OP 表示他不想要 nil 占位符。在这种情况下,可以使用以下内容:

local fields = redis.call('hkeys', 'a:hash:full:of:stuff');
local retval = {};
for i, field in pairs(fields) do
    if(string.match(tostring(field),'ev')) then
        retval[#retval+1] = {field, (string.match(tostring(field),'ev') ~= nil) }
    end
end
return retval
于 2013-06-10T19:58:41.860 回答
0

Eli 的回答很有效,但我认为这是因为在 Lua 中处理列表的方式存在一个微妙的问题。我想解释一下我的想法。

因此,作为测试,我在 中插入了一个额外的字段retval,有时它是 nil。我注意到在这些电话中,没有返回列表的其余部分。

我认为幕后发生的事情是 redis 正在处理整个列表,但是当它被返回时,它在第一个被截断nil。所以有时有一个列表,有时没有。作为一个黑客,我将脚本重写为

local fields = redis.call('hkeys', 'a:hash:full:of:stuff');
local retval = {};
local i = 0
for j, field in pairs(fields) do
    if string.find(field,"ev") then
        retval[i] = {field, string.match(field,'ev') }
        i = i+1;
    end
end
return retval

它奏效了!

所以 Eli 的答案有效,因为retval没有被截断。但是,当您需要解析返回的列表时,它会占用更多的带宽和 cpu 时间

于 2013-06-10T20:17:27.213 回答