관심 있는 각 열의 특정 값을 기준으로 여러 열이 있는 테이블을 필터링하는 방법을 알고 싶습니다.
여기에 이 예가 있습니다.
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
및 $6
0)를 포함하는 레코드를 삭제합니다. @EdMorton이 제안한대로
$ awk '{ x=4;for(i=3;i<=6;i++) if ($i==0) {x--;} }x' file
$3
$4
, $5
및 필드 중 하나가 $6
0이면 해당 필드가 포함된 레코드를 삭제합니다.
$ 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을 필터링하기 때문에 발생합니다.