简体   繁体   English

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

[英]Using sed on xargs variable isn't working inside shell expansion

I am attempting to do a batch key rename in Redis, using the shell to sed a replacement for each key name. 我试图在Redis中进行批量密钥重命名,使用shell为每个密钥名称替换一个替换。 (There doesn't seem to be a better way to do this in redis internally). (似乎没有更好的方法在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

I am expecting an output like this: "RENAME redis::staging::key redis::development::key" 我期待这样的输出: "RENAME redis::staging::key redis::development::key"

Instead I just get this: "RENAME redis::staging::key redis::staging::key" 相反,我得到这个: "RENAME redis::staging::key redis::staging::key"

The echo {} $(echo {}| sed 's/old/new/') is what is hanging me up... How does one properly achieve taking an xargs output and echo both the original and an edited version of that? echo {} $(echo {}| sed 's/old/new/')让我感到高兴...如何正确地实现xargs输出并回显原始版本和编辑版本? $(echo {} |sed) should work, right? $(echo {} |sed)应该有效,对吗? (If so, how can I do it correctly?) (如果是这样,我该怎么做呢?)

Solution with sed alone 单独使用sed的解决方案

sed, itself, is able to produce both the unmodified and the modified line: sed本身能够生成未修改和修改的行:

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

In the above, sed first adds the RENAME string to the beginning of the line. 在上面,sed首先将RENAME字符串添加到行的开头。 Then, the p command tells sed to print the line as it stands at that time (with "staging" still in it). 然后, p命令告诉sed打印当时的行(“暂存”仍然在其中)。 The next substitution puts in "development" and then that version is printed also. 下一个替换放入“开发”,然后也打印该版本。

Update: Suppose we want the output on one line: 更新:假设我们希望输出在一行:

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

The first s command above adds RENAME to the beginning and then doubles the line. 上面的第一个s命令将RENAME添加到开头,然后将该行加倍。 The second replaces the second occurrence of staging with development. 第二个用开发替换第二次登台。

Why didn't the xargs version do the substitution? 为什么xargs版本不进行替换?

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

Before xargs executes, bash processes the strings. 在xargs执行之前,bash处理字符串。 In particular, it sees $(echo {} | sed 's/staging/development/g') and it executes it ("command substitution") and gets the result {} . 特别是,它看到$(echo {} | sed 's/staging/development/g')并执行它(“命令替换”)并得到结果{} So, when xargs is finally run, it sees the command: 因此,当最终运行xargs时,它会看到命令:

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

Consequently, the s/staging/development/g substitution is never made. 因此,永远不会进行s/staging/development/g替换。

Making xargs and shell work together in proper order 使xargs和shell按正确顺序协同工作

There is a fix for this: 有一个解决方法:

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

The above puts the bash commands within single-quotes and passes them as arguments to sh . 上面将bash命令放在单引号中并将它们作为参数传递给sh This way, the string is not processed by the shell until after xargs has made the substitutions. 这样,在xargs进行替换之前,shell不会处理该字符串。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM