
다음과 같이 파일을 구문 분석하는 효율적인 방법이 있습니까?
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,000개가 넘는) 라인이 있으며 위에 표시된 대로 이 탭 델리 테이블을 추출해야 합니다. 이를 위한 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 -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 배열에 대한 암시적 분할 명령은 -n 또는 -p에 의해 생성된 암시적 while 루프 내에서 가장 먼저 수행됩니다.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
파이썬 솔루션
#!/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]
)를 사용하도록 분할되고 공백을 구분 기호로 사용하여 새 문자열로 다시 결합됩니다.