Solución con sed solo
sed, en sí mismo, es capaz de producir tanto la línea no modificada como la modificada:
$ echo "redis::staging::key" | sed 's/^/RENAME /; p; s/staging/development/g'
RENAME redis::staging::key
RENAME redis::development::key
En lo anterior, sed primero agrega la cadena RENAME al comienzo de la línea. Entonces, el p
El comando le dice a sed que imprima la línea tal como está en ese momento (con "puesta en escena" todavía en ella). La siguiente sustitución pone "desarrollo" y luego esa versión también se imprime.
Actualización: Supongamos que queremos la salida en una línea:
$ echo "redis::staging::key" | sed 's/.*/RENAME & &/; s/staging/development/2'
RENAME redis::staging::key redis::development::key
Los primeros s
El comando anterior agrega RENAME al principio y luego duplica la línea. El segundo reemplaza la segunda instancia de puesta en escena con desarrollo.
¿Por qué la versión xargs no hizo la sustitución?
xargs -I {} echo "RENAME {} $(echo {} | sed 's/staging/development/g')"
Antes de que se ejecute xargs, bash procesa las cadenas. En particular, ve $(echo {} | sed 's/staging/development/g')
y lo ejecuta ("sustitución de comando") y obtiene el resultado {}
. Entonces, cuando finalmente se ejecuta xargs, ve el comando:
xargs -I {} echo "RENAME {} {}"
En consecuencia, el s/staging/development/g
la sustitución nunca se realiza.
Hacer que xargs y shell funcionen juntos en el orden correcto
Hay una solución para esto:
$ echo "redis::staging::key" | xargs -I {} sh -c 'echo RENAME {} $(echo {} | sed 's/staging/development/g')'
RENAME redis::staging::key redis::development::key
Lo anterior pone los comandos bash entre comillas simples y los pasa como argumentos a sh
. De esta forma, la cadena no es procesada por el shell hasta que xargs haya realizado las sustituciones.