Извлечь информацию из файла

Извлечь информацию из файла

Есть ли эффективный способ анализа файла типа:

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

к:

CSQ=G      ENSG00000184731         ENST00000327669    Transcript  missense_variant

Паттерн всегда |||; - затем он начинается с CSQпятого поля и заканчивается им - однако это поле не всегда missense variant, а может быть и чем-то другим, например kdjdud.

В файле много (более 60 тыс.) строк, и мне нужно извлечь эту таблицу вкладок, как показано выше. Есть ли для этого решение на Python, Perl или AWK (или что-то еще)?

решение1

Давайте используем sed:

sed -r 's/.*\|\|\|;(CSQ[^|]+)\|([^|]+)\|([^|]+)\|([^|]+)\|([^|]+)\|.*/\1\t\2\t\3\t\4\t\5/' file.txt

pythonне быстр при работе с очень большими файлами, это было бы намного быстрее, чем python.

Пример:

% 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

решение2

Использование Perl:

perl -F'\|\|\|' -lane '$, = "\t"; @f = split(/;|\|/, $F[1]); shift(@f); splice(@f, 5); print(@f)' file
  • -F'\|\|\|': устанавливает разделитель полей ввода на |||;
  • -l: включает автоматическую обработку конца строки. Имеет два отдельных эффекта. Во-первых, он автоматически уничтожает $/ (разделитель входных записей) при использовании с -n или -p. Во-вторых, он присваивает $\ (разделитель выходных записей) значение octnum, так что любые операторы печати будут иметь этот разделитель, добавленный обратно. Если octnum опущен, устанавливает $\ в текущее значение $/.
  • -a: включает режим авторазделения при использовании с -n или -p. Неявная команда разделения массива @F выполняется как первое действие внутри неявного цикла while, созданного с помощью -n или -p.
  • n: заставляет Perl предполагать следующий цикл вокруг вашей программы, что заставляет ее перебирать аргументы имен файлов, что-то вроде sed -n или awk:

    LINE:
      while (<>) {
          ...             # your program goes here
      }
    
  • -e: может использоваться для ввода одной строки программы.
  • $, = "\t"; @f = split(/;|\|/, $F[1]); shift(@f); splice(@f, 5); print(@f): устанавливает разделитель выходных полей на \t, разбивает второе поле текущей строки на ;или |, удаляет первое пустое поле и печатает оставшиеся поля.
% 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
% 

решение3

Это должно вам подойти:

cut -d"|" -f4,5,6,7,8 filename.txt | sed 's/;//g' | sed 's/|/\t/g'

Пример:

$ 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

Объяснение

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

решение4

Решение на Python

#!/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]))

ТЕСТ

С оригинальной строкой OP, перепечатанной 3 раза и слегка отредактированной вinput.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

Объяснение

Скрипт открывает файл, указанный в командной строке как аргумент ( sys.argv[1]), и считывает файл построчно. Сначала мы используем re.split()функцию для разбиения каждой строки на несколько разделителей - 3 вертикальные черты или ;, что позволяет соответствующим данным содержаться в одной строке. Затем мы находим ту одну строку (которая содержит CSQ). Если мы ее находим, строка снова разбивается на список строк, теперь только с помощью .split()функции, использующей вертикальную черту в качестве разделителя. Полученный список разрезается, чтобы взять первые 5 элементов ( [0:5]часть) и снова объединяется в новую строку, используя пробел в качестве разделителя.

Связанный контент