Die zu bearbeitende Eingabedatei ist wie folgt (kann mehrere Zeilen enthalten):
bundle_id target_id length eff_length tot_counts uniq_counts est_counts eff_counts ambig_distr_alpha ambig_distr_beta fpkm fpkm_conf_low fpkm_conf_high solvable tpm
1 intron_FBgn0035847:4_FBgn0035847:3 61 0 0 0 0 0 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 F 0.00E+00
2 intron_FBgn0032515:2_FBgn0032515:4 72 0 0 0 0 0 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 F 0.00E+00
3 intron_FBgn0266486:5_FBgn0266486:4 58 0 0 0 0 0 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 F 0.00E+00
4 intron_FBgn0031359:10_FBgn0031359:7 4978 1430.739479 91 0 30.333333 105.539363 1.00E+00 1.00E+00 6.30E+00 1.77E+00 1.08E+01 F 1.42E+01
4 intron_FBgn0031359:10_FBgn0031359:8 4978 1430.739479 91 0 30.333333 105.539363 1.00E+00 1.00E+00 6.30E+00 1.77E+00 1.08E+01 F 1.42E+01
4 intron_FBgn0031359:10_FBgn0031359:9 4978 1430.739479 91 0 30.333333 105.539363 1.00E+00 1.00E+00 6.30E+00 1.77E+00 1.08E+01 F 1.42E+01
536 intron_CR31143:1_CR31143:2 40 0 0 0 0 0 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 F 0.00E+00
Für jede ID in der 2. Spalteintron_XXXXXXXX:X_XXXXXXXX:X, ich möchte die Zeichenfolge zwischenintron_und der 1.:(dazwischen beginnt die Zeichenfolge normalerweise, aber nicht immer, mit FBgn).
Dann habe ich eine Liste wie folgt (eine Spalte fürFBgnund die andere Spalte für den entsprechenden Namen, in den das FBgn konvertiert werden soll):
## FlyBase Gene Mapping Table
## Generated: Fri Dec 20 12:37:29 2013
## Using datasource: dbi:Pg:dbname=fb_2014_01_reporting;host=flysql9;port=5432...
FBgn0035847 mthl7
FBgn0032515 loqs
FBgn0266486 CG45085
FBgn0031359 CG18317
Dann möchte ich in der 1. Spalte der Liste nach der extrahierten Zeichenfolge suchen.
Wenn die extrahierte Zeichenfolge einen entsprechenden Wert in der 2. Spalte hat, möchte ich die gesamte ID ersetzenintron_FBgnXXXXXX:X_FBgnXXXXXX:Xmit dem entsprechenden Namen in der 2. Spalte.
Wenn die extrahierte Zeichenfolge in der 1. Spalte nicht vorhanden ist, möchte ich die gesamte ID ersetzenintron_XXXXXXXX:X_XXXXXXXX:Xmit der extrahierten Zeichenfolge.
Ich habe ein Skript wie das folgende:
ref="gene_map_table_fb_2014_01_short.tsv"
target="HC25_LNv_ZT02_intron_results.txt"
output="temptemp.txt"
declare -A map
while read line
do
if [[ ! -z "$line" ]] && [[ ! "$line" =~ ^#.* ]]
then
key=$(echo "$line" | cut -f 1)
value=$(echo "$line" | cut -f 2)
map[$key]=$value
fi
done < $ref
while read line
do
key=$(echo "$line" | sed -n 's/.*_\([^\.]*\)\:.*/\1/p' | head -1)
if [ ! -z "$key" ]
then
echo "$line" | sed 's/intron_[^[:space:]]*/'${map[$key]}'/g' >> $output
else
echo "$line" | sed 's/intron_[^[:space:]]*/'$key'/g' >> $output
fi
done < $target
Alles scheint gut zu funktionieren, außer dass in der Ausgabedatei die Zeilen fehlen, deren ID nicht mit FBgn beginnt.
Antwort1
Du kannst es schaffen:
cat gene_map_table_fb_2014_01_short.tsv |sed '1d' |awk {'print $2'} |awk 'BEGIN{FS=":"} {print $2}' |sed s/._//g
Zuerst caten Sie Ihre Datei, dann löschen Sie die erste Zeile (Spaltenüberschrift mit d1), dann drucken Sie alle Spalten aus, dann trennen Sie sie 4_FBgn0035847
mit awk 'BEGIN{FS=":"} {print $2}'
Dann eliminieren Sie number_
mitsed s/._//g
Die Ausgabe lautet:
FBgn0035847
FBgn0032515
FBgn0266486
1FBgn0031359
1FBgn0031359
1FBgn0031359
CR31143
Wenn Ihre Endzeile jedoch zusätzlich ist und Sie sie entfernen möchten, können Sie dies tun:
cat gene_map_table_fb_2014_01_short.tsv |sed '1d' |awk {'print $2'} |awk 'BEGIN{FS=":"} {print $2}' |sed s/._//g |sed '$d'
Die Ausgabe lautet also:
FBgn0035847
FBgn0032515
FBgn0266486
1FBgn0031359
1FBgn0031359
1FBgn0031359
Antwort2
Verwenden vonawk
Dadurch wird eine durch Tabulatoren getrennte Ausgabe erstellt:
$ awk -v OFS="\t" 'NR==FNR{a[$1]=$2;next} FNR==1{print;next} {sub(/intron_/, "", $2); sub(/:.*/,"",$2);if ($2 in a) $2=a[$2];print}' gene_map_table_fb_2014_01_short.tsv HC25_LNv_ZT02_intron_results.txt
bundle_id target_id length eff_length tot_counts uniq_counts est_counts eff_counts ambig_distr_alpha ambig_distr_beta fpkm fpkm_conf_low fpkm_conf_high solvable tpm
1 mthl7 61 0 0 0 0 0 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 F 0.00E+00
2 loqs 72 0 0 0 0 0 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 F 0.00E+00
3 CG45085 58 0 0 0 0 0 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 F 0.00E+00
4 CG18317 4978 1430.739479 91 0 30.333333 105.539363 1.00E+00 1.00E+00 6.30E+00 1.77E+00 1.08E+01 F 1.42E+01
4 CG18317 4978 1430.739479 91 0 30.333333 105.539363 1.00E+00 1.00E+00 6.30E+00 1.77E+00 1.08E+01 F 1.42E+01
4 CG18317 4978 1430.739479 91 0 30.333333 105.539363 1.00E+00 1.00E+00 6.30E+00 1.77E+00 1.08E+01 F 1.42E+01
536 CR31143 40 0 0 0 0 0 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 F 0.00E+00
Erläuterung:
-v OFS="\t"
Dadurch wird der Ausgabefeldtrenner zu einem Tabulator.
NR==FNR{a[$1]=$2;next}
Dadurch wird ein assoziatives Array erstellt, das
a
auf der ersten Datei in der Befehlszeile basiert, wobei die erste Spalte als Schlüssel und die zweite Spalte als Wert dient. Dernext
Befehl weist anawk
, den Rest der Befehle zu überspringen und zur nächsten Zeile zu springen.Die Mapping-Datei enthält einige Kommentarzeilen. Wir hätten leicht eine zusätzliche
if
Anweisung hinzufügen können, um zu verhindern, dass sie zum Array hinzugefügt werdena
. Da sie jedoch keinen Schaden anrichten, haben wir diese Komplikation übersprungen.FNR==1{print;next}
Dadurch wird die Kopfzeile unverändert gedruckt.
{sub(/intron_/, "", $2); sub(/:.*/,"",$2)
Dadurch wird der Ballast aus dem zweiten Feld entfernt, und nur die gewünschte Zeichenfolge bleibt übrig.
`wenn ($2 in a) $2=a[$2]
Wenn der String aus dem zweiten Feld als Schlüssel im Array vorhanden ist
a
, ersetzen wir ihn durch den entsprechenden Wert.print
Die überarbeitete Zeile wird ausgedruckt.
Verwenden vonbash
Ersetzen Sie im Skript
if [ ! -z "$key" ]
Mit:
if [[ "$key" && "${map[$key]}" ]]
An dieser Stelle scheint das Skript wissen zu müssen, ob key
in vorhanden war map
oder nicht. Der überarbeitete Test stellt nicht nur sicher, dass key
nicht leer ist, sondern dass es in ist map
.
Mit dieser einen Änderung erhalte ich die Ausgabe:
$ cat temptemp.txt
bundle_id target_id length eff_length tot_counts uniq_counts est_counts eff_counts ambig_distr_alpha ambig_distr_beta fpkm fpkm_conf_low fpkm_conf_high solvable tpm
1 mthl7 61 0 0 0 0 0 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 F 0.00E+00
2 loqs 72 0 0 0 0 0 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 F 0.00E+00
3 CG45085 58 0 0 0 0 0 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 F 0.00E+00
4 CG18317 4978 1430.739479 91 0 30.333333 105.539363 1.00E+00 1.00E+00 6.30E+00 1.77E+00 1.08E+01 F 1.42E+01
4 CG18317 4978 1430.739479 91 0 30.333333 105.539363 1.00E+00 1.00E+00 6.30E+00 1.77E+00 1.08E+01 F 1.42E+01
4 CG18317 4978 1430.739479 91 0 30.333333 105.539363 1.00E+00 1.00E+00 6.30E+00 1.77E+00 1.08E+01 F 1.42E+01
536 CR31143 40 0 0 0 0 0 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 F 0.00E+00
Als Randbemerkung zu text
: [ ! -z "$key" ]
Gibt true zurück, wenn key
nicht leer ist. Dies entspricht [ -n "$key" ]
. Da dies ein so gängiger Test ist, kann er weiter auf verkürzt werden [ "$key" ]
. Dies könnte verwendet werden, um mehrere Zeilen im bash
Skript zu vereinfachen.