Comment puis-je écrire un one-liner sed pour ajouter un caractère après chaque troisième caractère?

10

Donc, j'ai une chaîne qui ressemble à ceci:

AUGGCCAUGGCGCCCAGAACUGAGAUCAAUAGUACCCGUAUUAACGGGUGA

Et je veux diviser la chaîne en morceaux de 3 caractères délimités par un signe «+».

AUG+GCC+AUG+GCG+CCC+AGA+ACU+GAG+AUC+AAU+AGU+ACC+CGU+AUU+AAC+GGG+UGA

Et je veux le faire avec mon bon ami sed.

j'ai essayé

cat codons | sed -r 's/([A-Z]\{3\})/\1\+/g'

... sans succès.

Quelle sedcommande puis-je utiliser?

ixtmixilix
la source
1
N'est-ce pas en quelque sorte lié à Rosalind ? Juste curieux.
m0nhawk

Réponses:

16

Puisque vous ne voulez pas de suivi +, vous pouvez faire:

fold -w3 | paste -sd+ -

C'est-à-dire, foldles lignes sur l' idth de 3caractère w, et pasteces 3 lignes de caractère avec elles selfes avec +comme délimiteur qui en fait est comme changer chaque caractère de nouvelle ligne mais le dernier en a +. Si l'entrée avait plus d'une ligne, vous vous retrouverez avec ces lignes jointes avec une +qui peut ou non être ce que vous voulez.

Si vous en avez besoin sed, vous pouvez supprimer la fin +après:

sed 's/.../&+/g;s/+$//'
Stéphane Chazelas
la source
Pourriez-vous ajouter une courte explication de la façon dont cela fonctionne?
NN
@NN Cela fonctionne car +$correspond à un symbole plus juste avant la fin d'une ligne.
Chris Down
fold -w3casse la chaîne en 3 lignes de caractères. paste -sd+ -transforme les nouvelles lignes en +.
bahamat
12
sed 's/.../&+/g'

pour travailler, vous n'avez pas besoin d'échapper aux {}symboles:

sed -r 's/([A-Z]{3})/\1+/g'
se ruer
la source
1
qui savait!
j'étais
Les deux ajoutent un «+» de fin. Est-ce prévu?
NN
2

Cela pourrait fonctionner pour vous (GNU sed):

sed 's/...\B/&+/g' file
potong
la source
0

Si sed n'est pas un must, l'utilisation de Ruby pourrait être une alternative. L'interpréteur Ruby,, rubypeut être utilisé comme sed et awk en l'exécutant avec l' -noption qui le fait itérer sur son entrée. L'interpréteur peut ensuite être alimenté avec une ligne Ruby en l'ajoutant comme argument à l' -eoption (qui indique à l'interpréteur d'interpréter l'argument de -eplutôt que de rechercher un script dans un fichier).

Pour ce problème particulier, vous pouvez utiliser le one-liner suivant (adapté de /programming//a/3184271/789593 ):

ruby -ne 'puts $_.scan(/.{3}|.+/).join("+")'

En langage clair, il

  • correspond à 3 caractères ou au moins un caractère,, scan(/.{3}|.+/)dans la chaîne d'entrée, $_(dans ce cas, l'entrée devrait provenir de l'entrée standard) et place chaque correspondance dans un tableau,
  • se joint à la matrice dans une chaîne avec un « + » reliant chaque élément join("+"),
  • et l'imprime terminé par une nouvelle ligne puts.

Par exemple

echo "AUGGCCAUGGCGCCCAGAACUGAGAUCAAUAGUACCCGUAUUAACGGGUG" | ruby -ne 'puts $_.scan(/.{3}|.+/).join("+")'
AUG+GCC+AUG+GCG+CCC+AGA+ACU+GAG+AUC+AAU+AGU+ACC+CGU+AUU+AAC+GGG+UG

Notez qu'il n'ajoute aucun «+» de fin.

NN
la source