SRR3384742.Gene.out.tab
SRR3384743.Gene.out.tab
SRR3384744.Gene.out.tab
이 순서대로 여러 개의 파일과 더 많은 파일이 있습니다 . 이 파일에서 첫 번째와 네 번째 열을 추출하여 출력 파일에 저장합니다. 내 스크립트가 새 파일을 읽을 때 각 파일 끝에 데이터를 추가하는 대신 탭으로 구분된 방식으로 데이터를 추출해야 하는지 확인하려고 합니다.
입력 파일:
SRR3384742.Gene.out.tab
N_unmapped 313860 313860 313860
N_multimapping 5786679 5786679 5786679
N_noFeature 286816 31696770 438410
N_ambiguous 1283487 32117 65902
AT1G01010 301 0 301
AT1G01020 623 1 622
AT1G03987 5 5 0
AT1G01030 151 2 149
SRR3384743.Gene.out.tab
N_unmapped 780346 780346 780346
N_multimapping 4621162 4621162 4621162
N_noFeature 182428 28470016 362650
N_ambiguous 1451612 43059 117293
AT1G01010 154 3 151
AT1G01020 685 2 683
AT1G03987 0 0 0
AT1G01030 63 0 63
내가 얻는 결과는 다음과 같습니다.
SRR3384742.Gene.out.tab
AT1G01010 301
AT1G01020 622
AT1G03987 0
AT1G01030 149
SRR3384743.Gene.out.tab
AT1G01010 151
AT1G01020 683
AT1G03987 0
AT1G01030 63
원하는 출력:
SRR3384742.Gene.out.tab SRR3384743.Gene.out.tab
AT1G01010 301 151
AT1G01020 622 683
AT1G03987 0 0
AT1G01030 149 63
다음 스크립트를 시도했습니다.
for sample in *Gene.out.tab; do echo -en $sample "\n"; awk 'NR>4 {print $1 "\t" $4}' $sample; awk '{print $0, $sample}' OFS='\t' $sample; done > output
답변1
그러면 GNU를 사용하여 주석에 설명된 출력이 제공됩니다 awk
.
gawk 'FNR==1{names[c++]=FILENAME}
FNR>4{ lines[$1] = "x"lines[$1] ? lines[$1]"\t"$4 : $4; }
END{
for(i=0;i<=c;i++){
printf "\t%s",names[i]
}
printf "\n";
for(i in lines){
print i,lines[i]
}
}' *Gene.out.tab
SRR3384742.Gene.out.tab SRR3384743.Gene.out.tab
AT1G01010 301 151
AT1G01020 622 683
AT1G01030 149 63
AT1G03987 0 0
그리고 모든 것을 시각적으로 보기 좋게 정렬하려면 다음을 전달하세요 column
.
$ gawk 'FNR==1{names[c++]=FILENAME}FNR>4{ lines[$1] = "x"lines[$1] ? lines[$1]"\t"$4 : $4; } END{ for(i=0;i<=c;i++){printf "\t%s",names[i];} printf "\n"; for(i in lines){ print i,lines[i]}}' *Gene.out.tab | column -s$'\t' -t
SRR3384742.Gene.out.tab SRR3384743.Gene.out.tab
AT1G01010 301 151
AT1G01020 622 683
AT1G01030 149 63
AT1G03987 0 0
FNR
현재 처리 중인 파일의 줄 번호를 항상 보유하는 특수 awk 변수입니다. 현재 처리 중인 파일의 이름을 보유하는 FILENAME
GNU 특수 변수입니다 .awk
FNR==1{names[c++]=FILENAME}
: 이것이 입력 파일의 첫 번째 라인인 경우, 이 변수를 값이 filename 인 배열에 대한 인덱스로 사용c
하고 그 값을 yb 1 ( )만큼 증가시킵니다. 모든 파일이 처리된 후에는 첫 번째 파일 이름, 두 번째 파일 이름 등이 됩니다.names
c++
files[0]
files[1]
FNR>4{ lines[$1] = "x"lines[$1] ? lines[$1]"\t"$4 : $4; }
:이것은 다음과 동일합니다:if(FNR>4){ if("x"lines[$1]){ lines[$1]"\t"$4 else{ lines[$1] = $4 } }
현재 입력 파일의 줄 번호가 5개 이상인 경우 첫 번째 필드에 배열의 관련 값이 있는지 확인하세요
lines
. 사용 여부를 확인하는"x"lines[$i]
이유는 테스트가 거짓이지만lines[$1]
참 이므로 이를 방지할 수 있기 때문입니다. 따라서 값이 있으면 탭과 현재 줄의 두 번째 필드를 여기에 추가하고, 값이 없으면 현재 줄의 네 번째 필드에 설정합니다.0
x0
x
END{ ... }
: 모든 입력이 처리된 후 이 작업을 실행합니다.for(i=0;i<=c;i++){printf "\t%s",names[i]}; printf "\n";
:names
탭 문자 앞에 배열의 각 파일 이름을 인쇄합니다. 우리는 선두 탭이 헤더 행과 콘텐츠의 필드 수를 동일하게 유지하기를 원합니다. 파일 이름을 인쇄한 후 개행 문자를 인쇄합니다.for(i in lines){print i,lines[i]}
: 배열의 각 인덱스에 대해lines
인덱스(ID)를 인쇄한 다음 첫 번째 단계에서 저장된 관련 값을 인쇄합니다.
한정: 모든 출력 데이터를 메모리에 저장해야 합니다. 최신 시스템에서는 ID만 저장하고 파일당 ID당 하나의 값만 저장하므로 이는 실제로 문제가 되지 않습니다. 따라서 꽤 괜찮은 시스템에서는 차단하기 전에 많은 입력을 처리할 수 있어야 하지만 그렇지 않을 수도 있습니다. 문제가 된다. 데이터 양이 많아지면 문제가 있는 게 사실이다.
답변2
사용join
join -o '1.1 1.4 2.4' SRR3384742.Gene.out.tab SRR3384743.Gene.out.tab
N_unmapped 313860 780346
N_multimapping 5786679 4621162
N_noFeature 438410 362650
N_ambiguous 65902 117293
AT1G01010 301 151
AT1G01020 622 683
AT1G03987 0 0
AT1G01030 149 63
사용paste
paste
나는 이것이 당신이 찾고 있는 것이라고 생각합니다 :
paste <(cut -f 1,4 SRR3384742.Gene.out.tab) <(cut -f4 SRR3384743.Gene.out.tab)
N_unmapped 313860 780346
N_multimapping 5786679 4621162
N_noFeature 438410 362650
N_ambiguous 65902 117293
AT1G01010 301 151
AT1G01020 622 683
AT1G03987 0 0
AT1G01030 149 63
이 솔루션에서는 모든 항목에 다음이 *.tab
포함되어야 한다고 가정합니다.
- 행 수가 동일합니다.
- 같은 순서입니다.
다음은 헤더를 인쇄하고 여러 파일을 처리하는 스크립트입니다.
#!/bin/bash
set -euo pipefail
echo $(printf '%s\t' "$@")
first_file=$1
shift
fifos="<(cut -f1,4 $first_file) "$(printf '<(cut -f4 %s) ' "$@")
eval "paste $fifos"
command *.out.tab
SRR3384742.Gene.out.tab SRR3384743.Gene.out.tab
N_unmapped 313860 780346
N_multimapping 5786679 4621162
N_noFeature 438410 362650
N_ambiguous 65902 117293
AT1G01010 301 151
AT1G01020 622 683
AT1G03987 0 0
AT1G01030 149 63
답변3
for i in *.tab; do echo $i >/tmp/"$i"_out.txt ; awk '/^AT/{print $1,$4}' $i >> /tmp/"$i"_out.txt ; done
paste /tmp/*_out.txt| awk '{$3="";print }'
산출
SRR3384742.Gene.out.tab SRR3384743.Gene.out.tab
AT1G01010 301 151
AT1G01020 622 683
AT1G03987 0 0
AT1G01030 149 63