아래와 같은 데이터 파일이 있습니다.
Sample1 Sample2 Sample3 Sample4 Sample5 Sample6
./. ./. ./. ./. ./. ./.
./. ./. ./. ./. A/G ./.
./. ./. ./. ./. ./. ./.
A/A A/A A/G ./. ./. ./.
./만 포함된 모든 열을 제거하고 싶습니다. 나에게 맡겨
Sample1 Sample2 Sample3 Sample5
./. ./. ./. ./.
./. ./. ./. A/G
./. ./. ./. ./.
A/A A/A A/G ./.
나는 이것이 sed 또는 awk 명령이라고 생각하지만 도움을 주시면 감사하겠습니다.
답변1
사용 awk
:
awk -v na="./." '
BEGIN{OFS=FS}
NR==FNR && NR>1 {
for(i=1;i<=NF;i++){if($i!=na){s[i]=1}}
}
NR!=FNR {
for(l in s){true}
for(i in s){if (i!=l){printf "%s"OFS,$i} else {printf "%s\n",$i}}
}
' file file
파일이 탭으로 구분된 경우 BEGIN{OFS=FS}
로 변경해야 할 수도 있습니다.BEGIN{OFS=FS="\t"}
설명하다:
- 파일을 두 번 찾아보기(
awk ... file file
) NR==FNR
헤더를 제외하기 위해 처음으로 열( )에 있는 하나 이상의 값이 이 아닌NR>1
것을 확인하는 경우 열 번호를 변수에 저장합니다 .i
na="./."
s
- 두 번째 시간( ),
NR!=FNR
인쇄된 열 값에 포함된 각 열에 대해. (첫 번째 루프를 사용하면 인쇄할 마지막 열을 알 수 있습니다( 인쇄 또는 . 사이에서 결정할 수 있도록s
변수에 저장됨 ).l
OFS
\n
산출:
Sample1 Sample2 Sample3 Sample5
./. ./. ./. ./.
./. ./. ./. A/G
./. ./. ./. ./.
A/A A/A A/G ./.
파일이 탭으로 구분되어 있으면 출력이 조금 더 좋아질 것입니다 |column -t
. 그렇지 않으면 다음과 같이 추가할 수 있습니다.
Sample1 Sample2 Sample3 Sample5
./. ./. ./. ./.
./. ./. ./. A/G
./. ./. ./. ./.
A/A A/A A/G ./.
답변2
$ perl -F'\t' -lane '
push @{$AoA[$.-1]}, map { push @Cols2Keep, $_ if $. > 1 && $F[$_] ne "./." && !$seen{$_}++; $F[$_] } 0 .. $#F}
{print join "\t", @{$AoA[$_]}[sort { $a <=> $b } @Cols2Keep] for 0 .. $#AoA
' file.tsv
결과:
Sample1 Sample2 Sample3 Sample5
./. ./. ./. ./.
./. ./. ./. A/G
./. ./. ./. ./.
A/A A/A A/G ./.
피복재:
- @AoA 배열의 배열은 레코드 번호로 인덱싱된 배열에 파일을 저장합니다
$.
.$.
1부터 시작하고 배열은 우리에 의해 정규화Perl
되기 때문 입니다.0-indexed
$.
non ./.
@Cols2keep 배열은 요소가 발견된 열 번호를 저장합니다. 또한 중복되는 것을 원하지 않으므로 해싱을 통해 중복을 제거하고%seen
해시의 키는 이러한 열 번호입니다. 제한 사항은 첫 번째 레코드 확인을 건너뛴다는 것입니다.