Vous pouvez faire :
> echo XXXX | sed -e ':loop' -e 's/XX/XoX/g' -e 't loop'
XoXoXoX
Avec :
-e ':loop'
:Créer une étiquette "boucle"-e 't loop'
:Aller à l'étiquette "boucle" si la substitution précédente a réussi
Dans ce cas particulier, une analyse en avant ou en arrière serait utile. Je pense que GNU sed
ne les supporte pas. Avec perl
:
perl -ne 's/X(?=X)/Xo/g; print;'
Vous pouvez également utiliser lookbehind et lookahead comme :
s/(?<=X)(?=X)/o/g
Où :
(?<=X)
est un lookbehind positif, une assertion de longueur nulle qui s'assure que nous avons un X avant la position actuelle
(?=X)
est une anticipation positive, une assertion de longueur nulle qui garantit que nous avons un X après la position actuelle
Utilisation dans un one-liner perl :
perl -pe 's/(?<=X)(?=X)/o/g' inputfile
Où :
-p
fait supposer à Perl une boucle autour du programme avec une impression implicite de la ligne courante
La réponse en boucle est la manière générale de faire ce que vous demandez.
Cependant, dans le cas de vos données, en supposant que vous utilisez GNU, vous pouvez simplement faire :
sed 's/\B/o/g'
Le \b
et \B
les options sont des extensions regex :
\b
correspond aux limites des mots, c'est-à-dire la transition d'un caractère "mot" à un caractère "non-mot", ou vice-versa\B
correspond à l'opposé de\b
. c'est-à-dire les lacunes "à l'intérieur" des mots. Cela nous permet d'insérer des caractères à l'intérieur d'un mot mais pas à l'extérieur, selon les besoins.
Essayez-le en ligne.
Cela suppose que les caractères saisis sont en fait tous des caractères de "mot".
Alternativement, si vous n'avez pas GNU sed, ou si les caractères d'entrée ne sont pas tous des caractères "mot", vous pouvez toujours atteindre votre objectif sans boucle :
sed 's/./&o/g;s/o$//'
Cela place simplement un o
après chaque caractère, puis supprime le dernier o
de la chaîne.
Essayez-le en ligne.