
Tengo un archivo como este:
id target_id length eff_length
1 intron_FBgn0000721:20_FBgn0000721:18 1136 243.944268
1 intron_FBgn0000721:19_FBgn0000721:18 1122 240.237419
2 intron_FBgn0264373:2_FBgn0264373:3 56 0
3 intron_FBgn0027570:4_FBgn0027570:3 54 0
Para la segunda columna target_id
, solo quiero mantener la cadena (no siempre FBgnXXXX
, a veces otros nombres) entre intron_
la primera y la primera :
. Entonces, el nuevo archivo de salida tendrá el valor más simple para la columna 2, pero el resto del archivo seguirá siendo el mismo.
Intenté con el comando sed pero no sé cómo eliminar la parte que no necesito.
Respuesta1
Usando sed
y column
:
$ sed -E 's/ intron_([^:]*):[^[:space:]]*/ \1/' file | column -t
id target_id length eff_length
1 FBgn0000721 1136 243.944268
1 FBgn0000721 1122 240.237419
2 FBgn0264373 56 0
La parte clave de esto es el comando sustituto:
s/ intron_([^:]*):\S*/ \1/
Busca intron_
y guarda todo después intron_
y antes de los primeros dos puntos en la variable 1
. [^[:space:]]*
coincide con todo, desde esos dos puntos hasta el final del campo. Todo eso se reemplaza por el texto guardado en variable 1
.
Usando awk
con salida separada por tabulaciones:
$ awk -v "OFS=\t" '{$2=$2;sub(/intron_/, "", $2); sub(/:.*/, "", $2); print}' file
id target_id length eff_length
1 FBgn0000721 1136 243.944268
1 FBgn0000721 1122 240.237419
2 FBgn0264373 56 0
Explicación:
-v "OFS=\t"
Esto establece el separador de campo de salida en una pestaña. Esto ayuda a alinear las columnas, posiblemente haciéndolas
column
innecesarias.$2=$2
Al imprimir una línea,
awk
no cambiará a nuestro separador de campo de salida recién especificado a menos que cambiemos algo en la línea. Asignar el segundo campo al segundo campo es suficiente para garantizar que la salida tendrá pestañas.sub(/intron_/, "", $2)
Esto se elimina
intron_
del segundo campo.sub(/:.*/, "", $2)
Esto elimina todo lo que está después de los primeros dos puntos del segundo campo.
print
Esto imprime nuestra nueva línea.
Usar awk
con formato de columna personalizado
Esto es como lo anterior, pero se utiliza printf
para que podamos personalizar el formato de anchos y alineaciones de las columnas según lo deseemos:
$ awk '{sub(/intron_/, "", $2); sub(/:.*/, "", $2); printf "%-3s %-12s %8s %3s\n",$1,$2,$3,$4}' file
id target_id length eff_length
1 FBgn0000721 1136 243.944268
1 FBgn0000721 1122 240.237419
2 FBgn0264373 56 0
Aquí la declaración printf "%-3s %-12s %8s %3s\n",$1,$2,$3,$4
selecciona anchos de columna y alineaciones en el printf
estilo habitual.
Usar sed
y convertir de separados por tabulaciones a separados por comas
$ sed -E 's/ intron_([^:]*):[^[:space:]]*/ \1/; s/[[:space:]][[:space:]]*/,/g' file
id,target_id,length,eff_length
1,FBgn0000721,1136,243.944268
1,FBgn0000721,1122,240.237419
2,FBgn0264373,56,0
Respuesta2
Puedes usar perl
:
$ perl -anle '
BEGIN {$" = "\t"}
print "@{[@F]}" and next if $. == 1;
$F[1] = $1 if /_([^:]*):/;
print "@{[@F]}";
' file
id target_id length eff_length
1 FBgn0000721 1136 243.944268
1 FBgn0000721 1122 240.237419
2 FBgn0264373 56 0
3 FBgn0027570 54 0
Explicación
-a
: divide automáticamente cada línea en una matriz@F
.BEGIN {$" = "\t"}
: configuramos el separador de lista en tabulador\t
, se usa cuando una matriz o un segmento de matriz se interpola en una cadena entre comillas dobles.print "@{[@F]}" and next if $. == 1
: Imprimimos el encabezado, procesamos a la siguiente línea.$F[1] = $1 if /_([^:]*):/
: obtenemos el valor entre_
y primero:
, lo guardamos en el segundo elemento en@F
.print "@{[@F]}"
: simplemente imprima el resultado deseado.
Respuesta3
sed -e 'h;s/.*intron_[^:]*\(:[^[:space:]]*\).*/\1/;s/./ /g;;G;;s/\(.*\)\n\(.*\)intron_\([^:]*\):[^[:space:]]*/\2\3\1/' YourFile
En 1 sed (sin tubería) manteniendo la columna. Utiliza el buffer de retención
Versión Posix (así --posix
que GNU sed)