Solution avec sed seul
sed, lui-même, est capable de produire à la fois la ligne non modifiée et la ligne modifiée :
$ echo "redis::staging::key" | sed 's/^/RENAME /; p; s/staging/development/g'
RENAME redis::staging::key
RENAME redis::development::key
Dans ce qui précède, sed ajoute d'abord la chaîne RENAME au début de la ligne. Ensuite, le p
La commande indique à sed d'imprimer la ligne telle qu'elle se présente à ce moment-là (avec "staging" toujours dedans). La prochaine substitution met "développement" et ensuite cette version est également imprimée.
Mise à jour : Supposons que nous voulions la sortie sur une seule ligne :
$ echo "redis::staging::key" | sed 's/.*/RENAME & &/; s/staging/development/2'
RENAME redis::staging::key redis::development::key
Les premiers s
La commande ci-dessus ajoute RENAME au début, puis double la ligne. La seconde remplace la seconde occurrence de mise en scène avec développement.
Pourquoi la version xargs n'a-t-elle pas effectué la substitution ?
xargs -I {} echo "RENAME {} $(echo {} | sed 's/staging/development/g')"
Avant l'exécution de xargs, bash traite les chaînes. En particulier, il voit $(echo {} | sed 's/staging/development/g')
et il l'exécute ("substitution de commande") et obtient le résultat {}
. Ainsi, lorsque xargs est enfin exécuté, il voit la commande :
xargs -I {} echo "RENAME {} {}"
Par conséquent, les s/staging/development/g
la substitution n'est jamais faite.
Faire en sorte que xargs et shell fonctionnent ensemble dans le bon ordre
Il existe un correctif pour cela :
$ echo "redis::staging::key" | xargs -I {} sh -c 'echo RENAME {} $(echo {} | sed 's/staging/development/g')'
RENAME redis::staging::key redis::development::key
Ce qui précède place les commandes bash entre guillemets simples et les passe comme arguments à sh
. De cette façon, la chaîne n'est pas traitée par le shell tant que xargs n'a pas effectué les substitutions.