
Gibt es eine effiziente Möglichkeit, eine Datei wie diese zu analysieren:
2 41620 . T G 100 PASS AC=3;AF=0.000599042;AN=5008;NS=2504;DP=18872;EAS_AF=0;AMR_AF=0;AFR_AF=0;EUR_AF=0;SAS_AF=0.0031;AA=.|||;CSQ=G|ENSG00000184731|ENST00000327669|Transcript|missense_variant|954|954|318|K/N|aaA/aaC|||-1|tolerated(0.47)|benign(0)||||;GENCODE=ENST00000327669
Zu:
CSQ=G ENSG00000184731 ENST00000327669 Transcript missense_variant
Das Muster ist immer |||
; - dann beginnt es mit CSQ
und endet mit dem fünften Feld - dieses Feld ist jedoch nicht immer, missense variant
sondern kann auch etwas anderes sein, wie kdjdud
.
Die Datei enthält viele Zeilen (über 60.000) und ich müsste diese Tab-Deli-Tabelle wie oben gezeigt extrahieren. Gibt es dafür eine Python-, Perl- oder AWK-Lösung (oder eine andere Lösung)?
Antwort1
Verwenden wir sed
:
sed -r 's/.*\|\|\|;(CSQ[^|]+)\|([^|]+)\|([^|]+)\|([^|]+)\|([^|]+)\|.*/\1\t\2\t\3\t\4\t\5/' file.txt
python
ist nicht schnell beim Bearbeiten sehr großer Dateien, dies wäre viel schneller als python
.
Beispiel:
% cat file.txt
2 41620 . T G 100 PASS AC=3;AF=0.000599042;AN=5008;NS=2504;DP=18872;EAS_AF=0;AMR_AF=0;AFR_AF=0;EUR_AF=0;SAS_AF=0.0031;AA=.|||;CSQ=G|ENSG00000184731|ENST00000327669|Transcript|missense_variant|954|954|318|K/N|aaA/aaC|||-1|tolerated(0.47)|benign(0)||||;GENCODE=ENST00000327669
2 41620 . T G 100 PASS AC=3;AF=0.000599042;AN=5008;NS=2504;DP=18872;EAS_AF=0;AMR_AF=0;AFR_AF=0;EUR_AF=0;SAS_AF=0.0031;AA=.|||;CSQ=G|ENSG00000184731|ENST00000327669|Transcript|missense_variant|954|954|318|K/N|aaA/aaC|||-1|tolerated(0.47)|benign(0)||||;GENCODE=ENST00000327669
2 41620 . T G 100 PASS AC=3;AF=0.000599042;AN=5008;NS=2504;DP=18872;EAS_AF=0;AMR_AF=0;AFR_AF=0;EUR_AF=0;SAS_AF=0.0031;AA=.|||;CSQ=G|ENSG00000184731|ENST00000327669|Transcript|missense_variant|954|954|318|K/N|aaA/aaC|||-1|tolerated(0.47)|benign(0)||||;GENCODE=ENST00000327669
2 41620 . T G 100 PASS AC=3;AF=0.000599042;AN=5008;NS=2504;DP=18872;EAS_AF=0;AMR_AF=0;AFR_AF=0;EUR_AF=0;SAS_AF=0.0031;AA=.|||;CSQ=G|ENSG00000184731|ENST00000327669|Transcript|missense_variant|954|954|318|K/N|aaA/aaC|||-1|tolerated(0.47)|benign(0)||||;GENCODE=ENST00000327669
% sed -r 's/.*\|\|\|;(CSQ[^|]+)\|([^|]+)\|([^|]+)\|([^|]+)\|([^|]+)\|.*/\1\t\2\t\3\t\4\t\5/' file.txt
CSQ=G ENSG00000184731 ENST00000327669 Transcript missense_variant
CSQ=G ENSG00000184731 ENST00000327669 Transcript missense_variant
CSQ=G ENSG00000184731 ENST00000327669 Transcript missense_variant
CSQ=G ENSG00000184731 ENST00000327669 Transcript missense_variant
Antwort2
Mit Perl:
perl -F'\|\|\|' -lane '$, = "\t"; @f = split(/;|\|/, $F[1]); shift(@f); splice(@f, 5); print(@f)' file
-F'\|\|\|'
: setzt den Eingabefeldtrenner auf|||
;-l
: aktiviert die automatische Zeilenendeverarbeitung. Dies hat zwei verschiedene Auswirkungen. Erstens wird $/ (der Eingabedatensatztrenner) automatisch gelöscht, wenn es mit -n oder -p verwendet wird. Zweitens wird $\ (der Ausgabedatensatztrenner) mit dem Wert octnum versehen, sodass dieser Trenner bei allen Druckanweisungen wieder hinzugefügt wird. Wenn octnum weggelassen wird, wird $\ auf den aktuellen Wert von $/ gesetzt.-a
: schaltet den Autosplit-Modus ein, wenn er mit -n oder -p verwendet wird. Ein impliziter Split-Befehl für das @F-Array wird als erstes innerhalb der impliziten While-Schleife ausgeführt, die durch -n oder -p erzeugt wird.n
: bewirkt, dass Perl die folgende Schleife um Ihr Programm annimmt, die es über Dateinamenargumente iterieren lässt, ähnlich wie sed -n oder awk:LINE: while (<>) { ... # your program goes here }
-e
: kann verwendet werden, um eine Programmzeile einzugeben.$, = "\t"; @f = split(/;|\|/, $F[1]); shift(@f); splice(@f, 5); print(@f)
: setzt den Ausgabefeldtrenner auf\t
, teilt das zweite Feld der aktuellen Zeile an;
oder|
auf , entfernt das erste leere Feld und druckt die verbleibenden Felder.
% cat file
2 41620 . T G 100 PASS AC=3;AF=0.000599042;AN=5008;NS=2504;DP=18872;EAS_AF=0;AMR_AF=0;AFR_AF=0;EUR_AF=0;SAS_AF=0.0031;AA=.|||;CSQ=G|ENSG00000184731|ENST00000327669|Transcript|missense_variant|954|954|318|K/N|aaA/aaC|||-1|tolerated(0.47)|benign(0)||||;GENCODE=ENST00000327669
% perl -F'\|\|\|' -lane '$, = "\t"; @f = split(/;|\|/, $F[1]); shift(@f); splice(@f, 5); print(@f)' file
CSQ=G ENSG00000184731 ENST00000327669 Transcript missense_variant
%
Antwort3
Das sollte für Sie funktionieren:
cut -d"|" -f4,5,6,7,8 filename.txt | sed 's/;//g' | sed 's/|/\t/g'
Beispiel:
$ echo "2 41620 . T G 100 PASS AC=3;AF=0.000599042;AN=5008;NS=2504;DP=18872;EAS_AF=0;AMR_AF=0;AFR_AF=0;EUR_AF=0;SAS_AF=0.0031;AA=.|||;CSQ=G|ENSG00000184731|ENST00000327669|Transcript|missense_variant|954|954|318|K/N|aaA/aaC|||-1|tolerated(0.47)|benign(0)||||;GENCODE=ENST00000327669
" | cut -d"|" -f4,5,6,7,8 | sed 's/;//g' | sed 's/|/\t/g'
CSQ=G ENSG00000184731 ENST00000327669 Transcript missense_variant
Erläuterung
cut -d"|" -f4,5,6,7,8 filename.txt #-> split the line at | and return fields 4 to 8
| sed 's/;//g' #-> remove the ;
| sed 's/|/\t/g' #-> replace | with tab
Antwort4
Python-Lösung
#!/usr/bin/env python
import re,sys
with open(sys.argv[1]) as fd:
for line in fd:
pattern=[ x for x in re.split('\|\|\||;',line)
if 'CSQ' in x]
if pattern:
print(" ".join(pattern[0].split("|")[0:5]))
PRÜFEN
Mit der Originalzeile des OP, die dreimal neu eingefügt und leicht bearbeitet wurdeinput.txt
$ ./extract_pattern.py input.txt
CSQ=G ENSG00000184731 ENST00000327669 Transcript missense_variant
CSQ=G ENSG00000184731 ENST00000327669 Transcript random_variant
CSQ=G ENSG00000184731 ENST00000327669 Transcript other_variant
Erläuterung
Das Skript öffnet die in der Befehlszeile als Argument angegebene Datei ( sys.argv[1]
) und liest die Datei Zeile für Zeile. Wir verwenden zunächst re.split()
die Funktion, um jede Zeile in mehrere Trennzeichen aufzuteilen – 3 vertikale Striche oder ;
, wodurch die relevanten Daten in einem String enthalten sein können. Dann suchen wir diesen einen String (der enthält CSQ
). Wenn wir ihn finden, wird der String wieder in eine Liste von Strings aufgeteilt, jetzt nur unter Verwendung .split()
der Funktion mit vertikalem Strich als Trennzeichen. Die resultierende Liste wird aufgeteilt, um die ersten 5 Elemente (den [0:5]
Teil) zu übernehmen, und mit Leerzeichen als Trennzeichen wieder zu einem neuen String zusammengefügt.