¿Cómo escribo un sed one-liner para agregar un carácter después de cada tercer carácter?

10

Entonces, tengo una cadena que se ve así:

AUGGCCAUGGCGCCCAGAACUGAGAUCAAUAGUACCCGUAUUAACGGGUGA

Y quiero dividir la cadena en fragmentos de 3 caracteres delimitados por un signo '+'.

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

Y quiero hacer eso con mi buen amigo sed.

Lo intenté

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

... sin éxito.

¿Qué sedcomando puedo usar?

ixtmixilix
fuente
1
¿No está esto de alguna manera conectado con Rosalind ? Sólo curioso.
m0nhawk

Respuestas:

16

Como no quieres un seguimiento +, puedes hacer:

fold -w3 | paste -sd+ -

Es decir, foldlas líneas en idth de 3caracteres w, y pasteesas 3 líneas de caracteres con ellos selfos con +el deliminador, que en efecto es como cambiar cada carácter de nueva línea pero el último en un +. Si la entrada tenía más de una línea, terminará con esas líneas unidas con una +que puede o no ser lo que desea.

Si lo necesita sed, puede eliminar el final +después de:

sed 's/.../&+/g;s/+$//'
Stéphane Chazelas
fuente
¿Te importaría agregar una breve explicación de cómo funciona?
NN
@NN Funciona porque +$coincide con un símbolo más inmediatamente antes del final de una línea.
Chris Down
fold -w3rompe la cadena en 3 líneas de caracteres. paste -sd+ -convierte las nuevas líneas en +.
bahamat
12
sed 's/.../&+/g'

para comenzar a trabajar no necesita escapar de los {}símbolos:

sed -r 's/([A-Z]{3})/\1+/g'
prisa
fuente
1
¡quien sabe! Estaba tan cerca pero tan lejos ... gracias ...
ixtmixilix
Ambos agregan un '+' final. ¿Es esto intencionado?
NN
2

Esto podría funcionar para usted (GNU sed):

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

Si sed no es imprescindible, usar Ruby podría ser una alternativa. El intérprete de Ruby ruby, se puede usar como sed y awk ejecutándolo con la -nopción que lo hace iterar sobre su entrada. El intérprete puede ser alimentado con Ruby one-liner agregándolo como argumento a la -eopción (que le dice al intérprete que interprete el argumento en -elugar de buscar un script en un archivo).

Para este problema en particular, puede usar el siguiente one-liner (adaptado de /programming//a/3184271/789593 ):

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

En lenguaje sencillo

  • coincide con 3 caracteres o al menos un carácter, scan(/.{3}|.+/)en la cadena de entrada $_(en este caso, se espera que la entrada provenga de la entrada estándar) y coloca cada coincidencia en una matriz,
  • se une a la matriz en una cadena con un '+' la conexión de cada elemento, join("+"),
  • e imprime terminado por una nueva línea puts.

Por ejemplo

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

Tenga en cuenta que no agrega ningún '+' final.

NN
fuente