다음 파일이 있습니다
> head map.stats
ID=NbD053289.1.mrna1;Name=NbD053289.1;Parent=NbD053289.1.path1;coverage=100.0;identity=100.0;matches=702;mismatches=0;indels=0;unknowns=0
ID=NbD053288.1.mrna1;Name=NbD053288.1;Parent=NbD053288.1.path1;coverage=100.0;identity=99.8;matches=482;mismatches=1;indels=0;unknowns=0
ID=NbD053287.1.mrna1;Name=NbD053287.1;Parent=NbD053287.1.path1;coverage=100.0;identity=94.1;matches=738;mismatches=0;indels=46;unknowns=0
ID=NbD053281.1.mrna1;Name=NbD053281.1;Parent=NbD053281.1.path1;coverage=99.3;identity=99.1;matches=1476;mismatches=14;indels=0;unknowns=0
$identity >= 95 && $coverage == 100
이 출력을 얻을 수 있도록 필터링하고 싶습니다.
ID=NbD053289.1.mrna1;Name=NbD053289.1;Parent=NbD053289.1.path1;coverage=100.0;identity=100.0;matches=702;mismatches=0;indels=0;unknowns=0
ID=NbD053288.1.mrna1;Name=NbD053288.1;Parent=NbD053288.1.path1;coverage=100.0;identity=99.8;matches=482;mismatches=1;indels=0;unknowns=0
시도해 보았 grep -oP '(?<=identity=).*?(?=;)' map.stats | awk '$1 >= 99'
으나 그리 멀리 가지 못했습니다. 이 필터링은 어떻게 가능합니까?
미리 감사드립니다
답변1
또 다른 접근 방식은 다음과 같습니다.
$ awk -F'[;=]' '$10>=95 && $8 == 100' file
ID=NbD053289.1.mrna1;Name=NbD053289.1;Parent=NbD053289.1.path1;coverage=100.0;identity=100.0;matches=702;mismatches=0;indels=0;unknowns=0
ID=NbD053288.1.mrna1;Name=NbD053288.1;Parent=NbD053288.1.path1;coverage=100.0;identity=99.8;matches=482;mismatches=1;indels=0;unknowns=0
비결은 필드 구분 기호를 ;
또는 로 설정하는 것입니다 =
(그렇게 -F'[;=]'
합니다). 그러면 의 값은 identity
10번째 필드가 되고 의 값은 coverage
8번째 필드가 됩니다. awk
표현식이 true로 평가될 때 기본 작업은 현재 줄을 인쇄하는 것이므로 이 두 조건과 일치하는 모든 줄이 인쇄된다는 의미 입니다 $10>=95 && $8 == 100
.
실제로 GNU로도 이 작업을 수행할 수 있지만 전체 라인이 필요하고 뒤돌아보기를 사용할 이유가 없기 때문에 grep
해당 옵션이 필요하지 않습니다 . -o
필요한 것은 범위를 정의하는 것뿐입니다. ( ) 95
까지 의 값이 필요하므로 다음 과 사이에 숫자가 필요함을 의미합니다.100
>=95
9
5
9
100
$ grep -P 'coverage=100.0.*identity=(9[5..9]|100)' file
ID=NbD053289.1.mrna1;Name=NbD053289.1;Parent=NbD053289.1.path1;coverage=100.0;identity=100.0;matches=702;mismatches=0;indels=0;unknowns=0
ID=NbD053288.1.mrna1;Name=NbD053288.1;Parent=NbD053288.1.path1;coverage=100.0;identity=99.8;matches=482;mismatches=1;indels=0;unknowns=0
나는 동일성이 100보다 큰 값을 가질 수 없다고 가정하고 있다는 점에 유의하십시오. 이는 아마도 서열 보존을 보고 있고 100% 동일한 것보다 더 유사한 결과를 얻을 수 없기 때문에 안전한 가정처럼 보입니다.
답변2
먼저 다음을 사용하여 필드를 숫자로 변환해 보겠습니다.
awk -F= 'NR==1 { for(i=1;i<=NF;i++) printf "%2d %s\n",i,$i ;}' file
1 ID
2 NbD053289.1.mrna1;Name
3 NbD053289.1;Parent
4 NbD053289.1.path1;coverage
5 100.0;identity
6 100.0;matches
7 702;mismatches
8 0;indels
9 0;unknowns
10 0
따라서 Coverage는 5이고 Identity는 6입니다.
==
다음으로 awk는 문자열과 일치하므로 직접 사용할 수 없으므로 +1을 사용하여 숫자로 변환합니다.
이 출력
awk -F= '$6+1>96 && ($5+1) == 101' file
ID=NbD053289.1.mrna1;Name=NbD053289.1;Parent=NbD053289.1.path1;coverage=100.0;identity=100.0;matches=702;mismatches=0;indels=0;unknowns=0
ID=NbD053288.1.mrna1;Name=NbD053288.1;Parent=NbD053288.1.path1;coverage=100.0;identity=99.8;matches=482;mismatches=1;indels=0;unknowns=0
어디
-F=
=
awk에게 구분 기호 로 사용하도록 지시$6+1>96
위와 같이 숫자로 변환하고 필터링합니다.