
Tengo un problema de manipulación de texto que no he podido solucionar. Digamos que tengo un archivo de texto como el siguiente (text.txt). Habrá casos en los que a una línea con /locus_tag
le sigue una línea con /gene
y otros en los que no. Quiero encontrar todas las líneas que /locus_tag
no van seguidas de /gene
y luego usar una tabla (table.txt) como la siguiente para hacer coincidir a /locus_tag
y /gene
agregarla /gene
a mi archivo de texto después de su /locus_tag
.
Cualquier idea sobre cómo hacer esto sería genial.
/locus_tag="LOCUS_23770"
/note="ABC"
/locus_tag="LOCUS_23780"
/note="DEF"
/locus_tag="LOCUS_23980"
/note="GHI"
/locus_tag="LOCUS_24780"
/gene="BT_4758"
/note="ONP"
/locus_tag="LOCUS_25780"
/gene="BT_4768"
/note="WZX"
Mesa
/locus_tag /gene
LOCUS_00010 BT_4578
LOCUS_00020 BT_4577
LOCUS_00030 BT_2429
Respuesta1
Usando sus archivos vinculados, esto funciona
awk 'BEGIN{FS="[ =]+"; OFS="="}
BEGINFILE{fno++}
fno==1{locus["\""$1"\""]="\""$2"\""; }
fno>1{if (old ~ /LOCUS/ && $0 !~ /gene/) print "/gene", locus[old]; old=$3; print}
' table file1
Antes
/locus_tag="LOCUS_00030"
/note="WP_011108293.1 hypothetical protein (Bacteroides
Después
/locus_tag="LOCUS_00030"
/gene="BT_2429"
/note="WP_011108293.1 hypothetical protein (Bacteroides
Como no está familiarizado con awk
un tutorial
awk 'BEGIN{FS="[ =]+"; OFS="="}
# set up the input field separator as any group of spaces and/or =
# and set the output field separator as =
BEGINFILE{fno++}
# Whenever you open a file, increment the file counter fno
fno==1{locus["\""$1"\""]="\""$2"\""; }
# if this is the first file (i.e. table) load the array `locus[]`
# but wrap the fields in "..." so that they are exactly like the data file entries
fno>1{if (old ~ /LOCUS/ && $0 !~ /gene/) print "/gene", locus[old]; old=$3; print}
# if this is a data file
# if the current value of old (i.e. the previous line) is a LOCUS
# and && this line ($0) isn't a gene
# add a gene by indexing into the locus array based upon the value of old
# because old contains the last LOCUS we found
# in all cases
# set old to the 3rd field on the current line,
# which on any LOCUS line is the string "LOCUS_?????" and
# print the current line
# See note below re $2 vs $3 and FS
' table file1
# your input files, table must be first, you can have more data files if you want
O sin el multichar FS
, manténgalo old=$2
porque no se rompe en el espacio en blanco antes del texto en su archivo de datos, lo cual hace el multichar.
Lo siguiente establece el separador de campos según el archivo que esté leyendo FS=(fno==1)?" ":"="
. Espacio para la tabla y =
para los datos.
awk 'BEGIN{OFS="="}
BEGINFILE{fno++;FS=(fno==1)?" ":"="}
fno==1{locus["\""$1"\""]="\""$2"\""; }
fno>1{if (old ~ /LOCUS/ && $0 !~ /gene/) print "/gene", locus[old]; old=$2; print}
' table file1
Siempre que el archivo de la tabla no sea tan grande como para consumir memoria.
Y realice una prueba para insertar un mensaje en los genes faltantes si se adapta a algo más que el vacío./gene=
fno>1{if (old ~ /LOCUS/ && $0 !~ /gene/) print "/gene", (old in locus)?locus[old]:"\"GENE_MISSING_AT_LOCUS\""; old=$3; print}
Cambie la referencia del campo para old
que coincida con la versión que FS
está utilizando
/locus_tag="LOCUS_00020"
/gene="GENE_MISSING_AT_LOCUS"
/note="WP_008765457.1 hypothetical protein (Bacteroides
Editar
Al observar el archivo de muestra al que vinculó, simplemente hay un problema en la diferencia de formato entre la muestra anterior y sus datos reales que alteraron los números de campo. old=$2
solo era necesario cambiarlo a old=$3
. Corregido arriba.