merge les lignes en double dans les colonnes

Compte tenu d'un file comme celui-ci:

xyyzx xxyzzy xxxzy yzzyxxx xxxxx 

J'aimerais que la sortie soit:

 x y+ zx x+ y z+ y x+ zy y z+ y x+ x+ 

Est-ce possible de faire avec awk ou perl dans un oneliner? c'est-à-dire est-il possible de find un nombre quelconque de valeurs similaires dans les lignes et de les merge?

Cette version de perl peut également traiter des longueurs arbitraires de champ, pas seulement celles d'un seul caractère:

 $ perl -lpae 'for $i (@F){s/($i\s*){2,}/$i+ /g}' file x y+ zx x+ y z+ y x+ zy y z+ y x+ x+ 

Sur un file plus complexe:

 $ cat file foo foo foo bar foo bar foo bar bar foo foo foo xxx bar $ perl -lpae 'for $i (@F){s/($i\s*){2,}/$i+ /g}' file foo+ bar foo bar foo bar+ foo foo+ x+ bar 

Explication

Le -l supprime les lignes de return de chaque ligne d'input, le -a divise les champs d'input sur les espaces blancs dans le tableau @F et le -p imprime chaque ligne d'input après avoir appliqué le script donné par -e .

Le script lui-même itère sur chaque champ d'input (le tableau @F ), en enregistrant chacun comme $i . La substitution search 2 ou plus $i consécutifs suivis de 0 ou plus d'espaces et les remplace par $i+ .

 sed 's/\(.\)\( \1\)\{1,\}/\1+/g' <in >out 

 x y+ zx x+ y z+ y x+ zy y z+ y x+ x+ 

Avec BSD ou GNU sed :

 sed -Ee's/(.)( \1)+/\1+/g' <in >out 

Pour travailler avec des longueurs de champ arbitraires, il suffit de le faire avec des longueurs de champ arbitraires:

 sed -Ee 's/(...)( \1)+/\1+/g' <<"" xxx yyy yyy zzz xxx xxx xxx yyy zzz zzz yyy xxx xxx xxx zzz yyy yyy zzz zzz yyy xxx xxx xxx xxx xxx xxx xxx xxx 

 xxx yyy+ zzz xxx xxx+ yyy zzz+ yyy xxx+ zzz yyy yyy zzz+ yyy xxx+ xxx+ 

Ou avec l'input de @ terdon légèrement modifiée dans la deuxième ligne:

 sed -Ee's/(([^ ]+ *)+)( +\1)+/<\1>+/g' <<"" foo foo foo bar foo bar foo bar foo foo foo xxx bar 

 <foo>+ bar foo <bar foo>+ <foo>+ <x>+ bar