127.0.0.1:6379> dbsize
(integer) 0
127.0.0.1:6379> set user:1 1
OK
127.0.0.1:6379> set use:the:force luke
OK
127.0.0.1:6379> set non:user a
OK
Lua(保存为scanregex.lua):
local re = ARGV[1]
local nt = ARGV[2]
local cur = 0
local rep = {}
local tmp
if not re then
re = ".*"
end
repeat
tmp = redis.call("SCAN", cur, "MATCH", "*")
cur = tonumber(tmp[1])
if tmp[2] then
for k, v in pairs(tmp[2]) do
local fi = v:find(re)
if (fi and not nt) or (not fi and nt) then
rep[#rep+1] = v
end
end
end
until cur == 0
return rep
redis 127.0.0.1:6379> set a 0
OK
redis 127.0.0.1:6379> set b 1
OK
redis 127.0.0.1:6379> keys *
1) "a"
2) "b"
redis 127.0.0.1:6379> keys !a
(empty list or set) // I expected "b" here
redis 127.0.0.1:6379> keys !b
(empty list or set) // I expected "a" here
redis 127.0.0.1:6379> keys [!b]
1) "b"
redis 127.0.0.1:6379> keys [b]
1) "b"
redis 127.0.0.1:6379> keys [ab]
1) "a"
2) "b"
redis 127.0.0.1:6379> keys ![b]
(empty list or set)
5条答案
按热度按时间oyxsuwqo1#
**重要提示:**始终使用
SCAN
而不是(邪恶)KEYS
Redis的模式匹配在功能上有一定的局限性(参见util. c中
stringmatchlen
的实现),并且不能提供ATM所需要的模式匹配。1.扩展
stringmatchlen
以满足您的要求,可能将其作为PR提交。1.考虑一下你要做的事情--获取键的子集总是效率低下的,除非你索引它们,考虑跟踪所有非用户键的名字(比如在Redis集合中)。
1.如果您真的坚持要扫描整个键空间并与否定模式进行匹配,那么一种实现方法就是使用一点Lua魔法。
请考虑以下数据集和脚本:
Lua(保存为
scanregex.lua
):输出-第一次常规匹配,第二次补码:
wkyowqbh2#
@Karthikeyan Gopall你在上面的评论中钉住了它,这为我节省了一大堆时间。谢谢!
以下是您如何以各种组合方式使用它来获得您想要的:
dw1jzc5e3#
根据redis keys documentation,该命令支持glob样式模式,不支持正则表达式。
并且如果您查看文档,就会发现“!”字符并不像正则表达式那样特殊。
下面是我在自己的数据库中运行的一个简单测试:
所以我不认为你想通过keys命令实现的目标是可能的。
此外,keys命令不太适合生产环境,因为它会锁定整个redis数据库。
我建议使用scan命令获取所有密钥,将它们存储在本地,然后使用LUA删除它们
o4tp2gmn4#
这里有一个技巧可以用原生的redis命令来实现这一点(不需要Lua脚本或任何东西)。
如果您能够控制插入新密钥(您希望保留的密钥,删除所有其他内容,如您的问题)的时间,您可以:
1.在设置新密钥之前,请将所有现有密钥的过期时间设置为立即过期(see how)(按模式或所有方式)
1.加载新密钥
Redis会自动删除所有旧的密钥,而你只剩下你想要的新密钥。
6za6bjd05#
您还可以打印所有键并将其传递给grep。例如: