Solução apenas com sed
O sed, por si só, é capaz de produzir tanto a linha não modificada quanto a modificada:
$ echo "redis::staging::key" | sed 's/^/RENAME /; p; s/staging/development/g'
RENAME redis::staging::key
RENAME redis::development::key
No exemplo acima, o sed primeiro adiciona a string RENAME ao início da linha. Então, o
p
O comando diz ao sed para imprimir a linha como está naquele momento (com "staging" ainda nela). A próxima substituição coloca em "desenvolvimento" e então essa versão é impressa também. Atualização: Suponha que queremos a saída em uma linha:
$ echo "redis::staging::key" | sed 's/.*/RENAME & &/; s/staging/development/2'
RENAME redis::staging::key redis::development::key
Os primeiros
s
O comando acima adiciona RENAME ao início e dobra a linha. A segunda substitui a segunda ocorrência de encenação com desenvolvimento. Por que a versão xargs não fez a substituição?
xargs -I {} echo "RENAME {} $(echo {} | sed 's/staging/development/g')"
Antes de xargs ser executado, o bash processa as strings. Em particular, ele vê
$(echo {} | sed 's/staging/development/g')
e o executa ("substituição de comando") e obtém o resultado {}
. Então, quando o xargs finalmente é executado, ele vê o comando:xargs -I {} echo "RENAME {} {}"
Consequentemente, o
s/staging/development/g
substituição nunca é feita. Fazendo xargs e shell funcionarem juntos na ordem correta
Existe uma correção para isso:
$ echo "redis::staging::key" | xargs -I {} sh -c 'echo RENAME {} $(echo {} | sed 's/staging/development/g')'
RENAME redis::staging::key redis::development::key
O acima coloca os comandos bash entre aspas simples e os passa como argumentos para
sh
. Dessa forma, a string não é processada pelo shell até que xargs tenha feito as substituições.