
Ich habe ein Problem mit der Textbearbeitung, das ich nicht lösen konnte. Angenommen, ich habe eine Textdatei wie die folgende (text.txt). Es wird Fälle geben, in denen auf eine Zeile mit /locus_tag
eine Zeile mit folgt, /gene
und andere, in denen dies nicht der Fall ist. Ich möchte alle Zeilen finden, in denen /locus_tag
nicht auf folgt, /gene
und dann eine Tabelle (table.txt) wie die folgende verwenden, um das /locus_tag
mit einem abzugleichen /gene
und das /gene
nach seinem zu meiner Textdatei hinzuzufügen /locus_tag
.
Jede Idee, wie dies zu bewerkstelligen ist, wäre großartig.
/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"
Tisch
/locus_tag /gene
LOCUS_00010 BT_4578
LOCUS_00020 BT_4577
LOCUS_00030 BT_2429
Antwort1
Mit den verlinkten Dateien funktioniert das
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
Vor
/locus_tag="LOCUS_00030"
/note="WP_011108293.1 hypothetical protein (Bacteroides
Nach
/locus_tag="LOCUS_00030"
/gene="BT_2429"
/note="WP_011108293.1 hypothetical protein (Bacteroides
Da Sie mit awk
einer Komplettlösung nicht vertraut sind
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
Oder ohne das Multichar FS
, dann behalten Sie es bei old=$2
, weil es bei dem Leerzeichen vor dem Text in Ihrer Datendatei nicht umbricht, was bei dem Multichar der Fall ist.
Im Folgenden wird der Feldtrenner festgelegt, je nachdem, welche Datei Sie lesen FS=(fno==1)?" ":"="
. Platz für die Tabelle und =
für die Daten
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
Vorausgesetzt, die Tabellendatei ist nicht so groß, dass sie Speicher verbraucht.
Und setzen Sie einen Test ein, um eine Nachricht an fehlende Gene einzufügen, wenn es mehr passt als nur die leere/gene=
fno>1{if (old ~ /LOCUS/ && $0 !~ /gene/) print "/gene", (old in locus)?locus[old]:"\"GENE_MISSING_AT_LOCUS\""; old=$3; print}
Ändern Sie den Feldverweis für old
die Version, die FS
Sie verwenden
/locus_tag="LOCUS_00020"
/gene="GENE_MISSING_AT_LOCUS"
/note="WP_008765457.1 hypothetical protein (Bacteroides
Bearbeiten
Wenn man sich die Beispieldatei ansieht, auf die Sie verlinkt haben, erkennt man einfach ein Problem mit dem Formatierungsunterschied zwischen dem obigen Beispiel und Ihren tatsächlichen Daten, der die Feldnummern durcheinandergebracht hat. old=$2
Musste nur geändert werden in old=$3
. Oben korrigiert.