在xargs变量上使用sed在shell扩展中不起作用

时间:2014-02-07 19:28:08

标签: bash sed redis

我正在尝试在Redis中进行批量密钥重命名,使用shell为每个密钥名称替换一个替换。 (在内部redis中似乎没有更好的方法)。

redis-cli -n 5 KEYS "*::staging::*"| xargs -I {} echo "RENAME {} $(echo {} | sed 's/staging/development/g')" 
# Then pipe this command into redis-cli when working

我期待这样的输出: "RENAME redis::staging::key redis::development::key"

相反,我得到这个: "RENAME redis::staging::key redis::staging::key"

echo {} $(echo {}| sed 's/old/new/')让我感到很不舒服...... 如何正确地实现xargs输出并回显原始版本和编辑版本? $(echo {} |sed)应该有效,对吧? (如果是这样,我该怎么做呢?)

1 个答案:

答案 0 :(得分:7)

单独使用sed的解决方案

sed本身能够生成未修改和修改的行:

$ echo "redis::staging::key" | sed 's/^/RENAME /; p; s/staging/development/g'
RENAME redis::staging::key
RENAME redis::development::key

在上面,sed首先将RENAME字符串添加到行的开头。然后,p命令告诉sed打印当时的行(“暂存”仍然在其中)。下一个替换放入“开发”,然后也打印该版本。

更新:假设我们想要输出一行:

$ echo "redis::staging::key" | sed 's/.*/RENAME & &/; s/staging/development/2'
RENAME redis::staging::key redis::development::key

上面的第一个s命令将RENAME添加到开头,然后将该行加倍。第二次用开发替换第二次登台。

为什么xargs版本不进行替换?

xargs -I {} echo "RENAME {} $(echo {} | sed 's/staging/development/g')"

在xargs执行之前,bash处理字符串。特别是,它会看到$(echo {} | sed 's/staging/development/g')并执行它(“命令替换”)并获得结果{}。因此,当最终运行xargs时,它会看到命令:

xargs -I {} echo "RENAME {} {}"

因此,永远不会进行s/staging/development/g替换。

使xargs和shell以正确的顺序一起工作

有一个解决方法:

$ echo "redis::staging::key" | xargs -I {} sh -c 'echo RENAME {} $(echo {} | sed 's/staging/development/g')'
RENAME redis::staging::key redis::development::key

上面将bash命令放在单引号中,并将它们作为参数传递给sh。这样,在xargs进行替换之前,shell不会处理该字符串。