String 卢阿布尔人唐';在redis中没有预期的行为

String 卢阿布尔人唐';在redis中没有预期的行为,string,lua,redis,match,string-matching,String,Lua,Redis,Match,String Matching,我有剧本 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) }

我有剧本

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
  • 如果((string.match(tostring(field),'ev'))~=nil),则不需要执行
    。您只需执行
    if(string.match(tostring(field),'ev'))
  • 脚本失败的原因是lua不支持表中的nil键。如果设置
    some\u table[1]
    some\u table[2]
    some\u table[5]
    ,然后返回数组,它看起来会以
    some\u 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
    
    我想你也可以用,但我还没有玩过,所以不能在这里提供太多信息

    [编辑]OP声明他不想要零占位符。在这种情况下,可以使用以下各项:

    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
    

    Eli的答案是可行的,但我认为这是因为Lua处理列表的方式存在微妙的问题。我想解释一下我的想法

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

    我认为在幕后发生的是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时间。在调试过程中,脚本中有一些额外的内容。这是可行的,但不是optimal@PeterKlipfel在哪些方面不是最优的?您也许可以通过使用默认表来提高一点点性能,但我怀疑这会对基准测试产生任何影响。我的意思是我在回答中所说的。我应该指定它对于我的用例不是最佳的,这将包括解析出放入数组中的nil值。我确信我的解决方案可以被预绑定,但它使用的内存较少。您最初的解决方案有一个与
    hkeys
    调用大小相同的数组,返回时带有零占位符。如果您想避免使用nil占位符,那么首先为什么要问这个问题?不管怎样,如果你想要的话,我会用一种更简洁的方式修改我的答案,以避免占位符。对不起,我不是有意让自己听起来像个朋克。我给出了我的答案,因为在任何人遇到这个答案的情况下,gotcha可能有助于调试。它的好处是返回一个较小的列表。我不知道为什么我没有把我的名单拿回来