Puedes hacer:
> echo XXXX | sed -e ':loop' -e 's/XX/XoX/g' -e 't loop'
XoXoXoX
Con:
-e ':loop'
:Crear una etiqueta de "bucle"-e 't loop'
:salta a la etiqueta "bucle" si la sustitución anterior fue exitosa
En este caso particular, sería útil mirar hacia adelante o hacia atrás. Creo que GNU sed
no es compatible con estos. Con perl
:
perl -ne 's/X(?=X)/Xo/g; print;'
También puede usar mirar hacia atrás y mirar hacia adelante como:
s/(?<=X)(?=X)/o/g
donde:
(?<=X)
es una mirada hacia atrás positiva, una afirmación de longitud cero que asegura que tenemos una X antes de la posición actual
(?=X)
es una anticipación positiva, una afirmación de longitud cero que asegura que tenemos una X después de la posición actual
Usando en una sola línea de Perl:
perl -pe 's/(?<=X)(?=X)/o/g' inputfile
donde:
-p
hace que Perl asuma un bucle alrededor del programa con una impresión implícita de la línea actual
La respuesta en bucle es la forma general de hacer lo que pides.
Sin embargo, en el caso de sus datos, asumiendo que está usando GNU, simplemente puede hacer:
sed 's/\B/o/g'
El \b
y \B
las opciones son extensiones de expresiones regulares:
\b
coincide con los límites de las palabras, es decir, la transición de un carácter de "palabra" a un carácter "sin palabra", o viceversa\B
coincide con lo contrario de\b
. es decir, los espacios "dentro" de las palabras. Esto nos permite insertar caracteres dentro de una palabra pero no fuera, según sea necesario.
Pruébelo en línea.
Esto supone que los caracteres de entrada son, de hecho, todos los caracteres de "palabra".
Alternativamente, si no tiene GNU sed, o si los caracteres de entrada no son todos caracteres de "palabra", aún puede lograr su objetivo sin repetir:
sed 's/./&o/g;s/o$//'
Esto simplemente coloca un o
después de cada carácter y luego elimina el o
final de la cadena.
Pruébelo en línea.