두 가지 조건을 사용하여 파일 필터링

두 가지 조건을 사용하여 파일 필터링

다음 파일이 있습니다

> 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'[;=]'합니다). 그러면 의 값은 identity10번째 필드가 되고 의 값은 coverage8번째 필드가 됩니다. awk표현식이 true로 평가될 때 기본 작업은 현재 줄을 인쇄하는 것이므로 이 두 조건과 일치하는 모든 줄이 인쇄된다는 의미 입니다 $10>=95 && $8 == 100.


실제로 GNU로도 이 작업을 수행할 수 있지만 전체 라인이 필요하고 뒤돌아보기를 사용할 이유가 없기 때문에 grep해당 옵션이 필요하지 않습니다 . -o필요한 것은 범위를 정의하는 것뿐입니다. ( ) 95까지 의 값이 필요하므로 다음 과 사이에 숫자가 필요함을 의미합니다.100>=95959100

$ 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위와 같이 숫자로 변환하고 필터링합니다.

관련 정보