awk를 사용하여 테이블을 필터링하는 방법

awk를 사용하여 테이블을 필터링하는 방법

관심 있는 각 열의 특정 값을 기준으로 여러 열이 있는 테이블을 필터링하는 방법을 알고 싶습니다.

여기에 이 ​​예가 있습니다.

    Chr1    16644   0       0       1       1
    Chr1    16645   0       0       1       1
    Chr1    16646   0       0       1       1
    Chr1    16647   0       0       1       1
    Chr1    16648   0       0       1       1
    Chr1    16649   0       0       1       1
    Chr1    16650   0       0       1       1
    Chr1    16651   0       0       1       1
    Chr1    16782   0       0       0       0
    Chr1    16783   0       0       0       0
    Chr1    16784   0       0       0       0
    Chr1    16785   0       0       0       0
    Chr1    16786   0       0       1       1
    Chr1    16787   0       0       1       1
    Chr1    16788   0       0       1       1
    Chr1    16789   0       0       1       1
    Chr1    16790   0       0       1       1

3, 4, 5, 6열에서 0이 포함된 모든 행을 삭제하고 싶습니다.

난 이미 시도했어

cat STARsamples_read_depth.txt | awk '$3 != 0 && $4 != 0&& $5 != 0 && $6 != 0' | less

그러나 4개 열 모두가 아닌 일부 열만 0인 행도 삭제합니다.

그것을 할 수 있는 방법이 있나요?

감사해요

아사

답변1

awk를 사용하면 관심 있는 필드를 연결하면 0이 아닌 숫자가 생성되는지 테스트할 수 있습니다.

$ awk '($3$4$5$6)+0' file
    Chr1    16644   0       0       1       1
    Chr1    16645   0       0       1       1
    Chr1    16646   0       0       1       1
    Chr1    16647   0       0       1       1
    Chr1    16648   0       0       1       1
    Chr1    16649   0       0       1       1
    Chr1    16650   0       0       1       1
    Chr1    16651   0       0       1       1
    Chr1    16786   0       0       1       1
    Chr1    16787   0       0       1       1
    Chr1    16788   0       0       1       1
    Chr1    16789   0       0       1       1
    Chr1    16790   0       0       1       1

또는 어떤 이유로든 각 필드를 개별적으로 테스트하려는 경우 다음을 수행하세요.

$ awk '{for (i=3; i<=6; i++) if ($i != 0) { print; next } }' file
    Chr1    16644   0       0       1       1
    Chr1    16645   0       0       1       1
    Chr1    16646   0       0       1       1
    Chr1    16647   0       0       1       1
    Chr1    16648   0       0       1       1
    Chr1    16649   0       0       1       1
    Chr1    16650   0       0       1       1
    Chr1    16651   0       0       1       1
    Chr1    16786   0       0       1       1
    Chr1    16787   0       0       1       1
    Chr1    16788   0       0       1       1
    Chr1    16789   0       0       1       1
    Chr1    16790   0       0       1       1

질문에 표시된 것처럼 입력이 정수가 아닐 수 있는 경우(주석 참조) 위의 두 번째 스크립트를 사용하거나 연결에 대한 숫자 비교 대신 문자열로 만들 수 있습니다.

awk '($3$4$5$6) != "0000"' file

답변2

의견에서 @Devon이 언급 ||했듯이 &&.

그 이유는 최소한 다음 행을 표시하고 싶기 때문입니다.하나3, 4, 5, 6열의 값은 0과 다릅니다.

이것은 이해의 또 다른 방법입니다. 열이 모두 0인 행을 삭제하려고 합니다. 반대 관점에서 시작해 보겠습니다.인쇄이 열은 모두 0인 행입니다. 이것은 매우 간단합니다.

awk '$3 == 0 && $4 == 0 && $5 == 0 && $6 == 0'

이제 당신은 원한다상하 반전이 명령문은 모든 행을 표시합니다.아니요위의 조건을 충족하세요. 그러니 그 말을 부정하면 됩니다.

awk '(!($3 == 0 && $4 == 0 && $5 == 0 && $6 == 0))'

그런데 위 명령도 귀하의 요구 사항을 충족합니다.

어쨌든 따르면논리적 부정 규칙, 명제의 부정"ㅏ그리고두번째""A가 아니야또는B는 아니야”. 따라서 이 진술을 거부하려면 다음을 수행하십시오.

$3 == 0 && $4 == 0 && $5 == 0 && $6 == 0

모든 표현식을 부정하고 모두 변환해야 합니다."그리고"운영자"또는".

$3 != 0 || $4 != 0 || $5 != 0 || $6 != 0

이제 명령이 작동하지 않는 이유를 더 잘 이해할 수 있습니다. 사용하는 진술의 부정은 다음과 같습니다.

$3 == 0 || $4 == 0 || $5 == 0 || $6 == 0

이는 최소한 다음의 모든 행을 삭제한다는 것을 의미합니다.하나열(모두는 아님)이 0입니다.

답변3

사용 awk:

$ awk '!/(\s+0){4}$/' file
Or
$ awk '!/([[:space:]]+0){4}$/' file

두 번째 명령에는 POSIX awk가 필요합니다.

모든 필드(즉 $3, $4, , $5$60)를 포함하는 레코드를 삭제합니다. @EdMorton이 제안한대로

$ awk '{ x=4;for(i=3;i<=6;i++) if ($i==0) {x--;} }x' file

$3$4, $5및 필드 중 하나가 $60이면 해당 필드가 포함된 레코드를 삭제합니다.

$ awk '{ x=1;for(i=3;i<=6;i++) if ($i==0) {x=0;break;} }x'

for 루프는 (i=3;i<=6;i++)필드 3,4,5,6을 필터링하기 때문에 발생합니다.

관련 정보