공백으로 구분된 3개의 파일이 있으며 약 340만 개의 행이 있습니다(그러나 행 수가 정확히 같지 않고 "태그" 열을 기준으로 정렬되어 있습니다). 그것들은 다음과 같습니다:
head neu1
Chr BP Marker MAF A1 A2 Direction pValue N 1 100000012 1:100000012:G:T 0.229925 T G + 0.650403 1594 1 100000827 1:100000827:C:T 0.287014 T C + 0.955449 1594 1 100002713 1:100002713:C:T 0.097867 T C - 0.290455 1594 1 100002882 1:100002882:T:G 0.287014 G T + 0.955449 1594 1 100002991 1:100002991:G:A 0.097867 A G - 0.290455 1594 1 100004726 1:100004725:G:A 0.132058 A G + 0.115005 1594
head nep1
Chr BP Marker MAF A1 A2 Direction pValue N 1 100000012 1:100000012:G:T 0.2300430 T G - 0.1420030 1641 1 100000827 1:100000827:C:T 0.2867150 T C - 0.2045580 1641 1 100002713 1:100002713:C:T 0.0975015 T C - 0.0555507 1641 1 100002882 1:100002882:T:G 0.2867150 G T - 0.2045580 1641 1 100002991 1:100002994:G:A 0.0975015 A G - 0.0555507 1641 1 100004726 1:100004726:G:A 0.1325410 A G - 0.8725660 1641
head ret1
Chr BP Marker MAF A1 A2 Direction pValue N 1 100000012 1:100000012:G:T 0.2322760 T G - 0.230383 1608 1 100000827 1:100000827:C:T 0.2882460 T C - 0.120356 1608 1 100002713 1:100002713:C:T 0.0982587 T C - 0.272936 1608 1 100002882 1:100002883:T:G 0.2882460 G T - 0.120356 1608 1 100002991 1:100002991:G:A 0.0982587 A G - 0.272936 1608 1 100004726 1:100004726:G:A 0.1340170 A G - 0.594538 1608
"표시" 열(세 번째 열)의 값 이 3개의 원본 파일 모두에 대해 동일한 행만 포함하는 neu2
3 개의 파일을 더 생성하는 방법이 있습니까 ?nep2
ret2
출력 파일에는 초기 파일의 9개 열이 모두 포함되어야 한다는 점을 언급해야 합니다.
예상되는 출력은 다음 3개 파일입니다.
head neu2
Chr BP Marker MAF A1 A2 Direction pValue N 1 100000012 1:100000012:G:T 0.229925 T G + 0.650403 1594 1 100000827 1:100000827:C:T 0.287014 T C + 0.955449 1594 1 100002713 1:100002713:C:T 0.097867 T C - 0.290455 1594
head nep1
Chr BP Marker MAF A1 A2 Direction pValue N 1 100000012 1:100000012:G:T 0.2300430 T G - 0.1420030 1641 1 100000827 1:100000827:C:T 0.2867150 T C - 0.2045580 1641 1 100002713 1:100002713:C:T 0.0975015 T C - 0.0555507 1641
head ret1
Chr BP Marker MAF A1 A2 Direction pValue N 1 100000012 1:100000012:G:T 0.2322760 T G - 0.230383 1608 1 100000827 1:100000827:C:T 0.2882460 T C - 0.120356 1608 1 100002713 1:100002713:C:T 0.0982587 T C - 0.272936 1608
3개 파일 각각의 헤더는 초기 파일과 결과 파일에 각각 9개씩 있습니다.
Chr BP Marker MAF A1 A2 Direction pValue N
답변1
이는 빠르고 효율적이어야 합니다. 그것은 join
(의 일부를 사용합니다GNU 핵심 도구) 및 field
(의 일부탱고 도구):
# This finds the matching lines and makes it into a big file with 25 columns
join -1 3 -2 3 neu1 nep1 | join -1 1 -2 3 - ret1 |
# Now split the right columns
# field is https://gitlab.com/ole.tange/tangetools/-/tree/master/field
tee > >(field 2-3,1,4-9 > neu2) >(field 10-11,1,12-17 > nep2) >(field 18-19,1,20-25 > ret2)
답변2
$ cat ../tst.awk
ARGIND < 4 {
if ( FNR == 1 ) {
ARGV[ARGC] = FILENAME
ARGC++
}
if ( !seen[ARGIND,$3]++ ) {
cnt[$3]++
}
next
}
FNR == 1 {
close(out)
out = FILENAME
sub(/1/,"2",out)
}
cnt[$3] == 3 {
print $0 " > " out
}
.
$ awk -f ../tst.awk neu1 nep1 ret1
Chr BP Marker MAF A1 A2 Direction pValue N > neu2
1 100000012 1:100000012:G:T 0.229925 T G + 0.650403 1594 > neu2
1 100000827 1:100000827:C:T 0.287014 T C + 0.955449 1594 > neu2
1 100002713 1:100002713:C:T 0.097867 T C - 0.290455 1594 > neu2
Chr BP Marker MAF A1 A2 Direction pValue N > nep2
1 100000012 1:100000012:G:T 0.2300430 T G - 0.1420030 1641 > nep2
1 100000827 1:100000827:C:T 0.2867150 T C - 0.2045580 1641 > nep2
1 100002713 1:100002713:C:T 0.0975015 T C - 0.0555507 1641 > nep2
Chr BP Marker MAF A1 A2 Direction pValue N > ret2
1 100000012 1:100000012:G:T 0.2322760 T G - 0.230383 1608 > ret2
1 100000827 1:100000827:C:T 0.2882460 T C - 0.120356 1608 > ret2
1 100002713 1:100002713:C:T 0.0982587 T C - 0.272936 1608 > ret2
테스트 완료 후 실제로 필요한 출력 파일을 생성 print $0 " > " out
하도록 변경합니다 . print > out
위의 내용은 에 대해 GNU awk를 사용합니다 ARGIND
. GNU awk가 없으면 FNR==1 { ARGIND++ }
스크립트의 첫 번째 줄에 추가하면 됩니다.
답변3
이것은 참으로 좋은 질문입니다. 파일이 세 번째 열을 기준으로 오름차순으로 정렬되어 있다고 확신하는 경우 SQL World의 병합 조인에 유사한 접근 방식을 사용하는 것이 좋습니다. 파일 정렬은 bash에서 문자열을 비교하는 데 사용되는 것과 동일한 정렬 기능을 사용하여 수행되어야 합니다. 아래 스크립트에는 bash가 필요합니다. 다음을 통해 호출해야 합니다.
$ script file1 file2 file3
3개의 출력 파일(file1.out, file2.out, file3.out)이 생성됩니다. 여기에는 모든 입력 파일에 있는 세 번째 열에 값이 있는 해당 소스 파일의 행이 포함되어 있습니다. 해당 값을 가진 모든 행은 ".out" 파일에 있습니다.
#!/bin/bash
Fil1="$1"
Fil2="$2"
Fil3="$3"
# Opening file descriptors for reading
exec 10<"$Fil1"
exec 20<"$Fil2"
exec 30<"$Fil3"
# Open output files
exec 11>"$Fil1".out
exec 21>"$Fil2".out
exec 31>"$Fil3".out
# First line is copied without changes.
IFS= read -r -u 10 Line1
printf "%s\n" "$Line1" >&11
IFS= read -r -u 20 Line2
printf "%s\n" "$Line2" >&21
IFS= read -r -u 30 Line3
printf "%s\n" "$Line3" >&31
# Prepare to walk through files, searching for identical values in the third column.
IFS= read -r -u 10 Line1
if [ $? -eq 0 ] ; then RC1=0; else RC1=1; fi
read -r F11 F12 F13 F1 <<< "$Line1"
IFS= read -r -u 20 Line2
if [ $? -eq 0 ] ; then RC2=0; else RC2=1; fi
read -r F21 F22 F23 F2 <<< "$Line2"
IFS= read -r -u 30 Line3
if [ $? -eq 0 ] ; then RC3=0; else RC3=1; fi
read -r F31 F32 F33 F3 <<< "$Line3"
while [ $RC1 -eq 0 ] && [ $RC2 -eq 0 ] && [ $RC3 -eq 0 ]
do
while [ "$F23" \< "$F13" ]
do
IFS= read -r -u 20 Line2
if [ $? -eq 0 ] ; then RC2=0; else RC2=1; break; fi
read -r F21 F22 F23 F2 <<< "$Line2"
done
if [ $RC2 -ne 0 ]; then break; fi
if [ "$F23" = "$F13" ]
then
FFF="$F23"
while [ "$F33" \< "$FFF" ]
do
IFS= read -r -u 30 Line3
if [ $? -eq 0 ] ; then RC3=0; else RC3=1; break; fi
read -r F31 F32 F33 F3 <<< "$Line3"
done
if [ $RC3 -ne 0 ]; then break; fi
if [ "$F33" = "$FFF" ]
then
while [ "$F23" = "$FFF" ]
do
printf "%s\n" "$Line2" >&21
IFS= read -r -u 20 Line2
if [ $? -eq 0 ] ; then RC2=0; else RC2=1; break; fi
read -r F21 F22 F23 F2 <<< "$Line2"
done
while [ "$F13" = "$FFF" ]
do
printf "%s\n" "$Line1" >&11
IFS= read -r -u 10 Line1
if [ $? -eq 0 ] ; then RC1=0; else RC1=1; break; fi
read -r F11 F12 F13 F1 <<< "$Line1"
done
while [ "$F33" = "$FFF" ]
do
printf "%s\n" "$Line3" >&31
IFS= read -r -u 30 Line3
if [ $? -eq 0 ] ; then RC3=0; else RC3=1; break; fi
read -r F31 F32 F33 F3 <<< "$Line3"
done
if [ $RC1 -ne 0 ] || [ $RC2 -ne 0 ] || [ $RC3 -ne 0 ]; then break; fi
fi
fi
while [ "$F33" \> "$F23" ]
do
IFS= read -r -u 20 Line2
if [ $? -eq 0 ] ; then RC2=0; else RC2=1; break; fi
read -r F21 F22 F23 F2 <<< "$Line2"
done
while [ "$F23" \> "$F13" ]
do
IFS= read -r -u 10 Line1
if [ $? -eq 0 ] ; then RC1=0; else RC1=1; break; fi
read -r F11 F12 F13 F1 <<< "$Line1"
done
done
# close files
exec 10>&-
exec 11>&-
exec 20>&-
exec 21>&-
스크립트는 파일을 한 번만 읽고 앞으로 번갈아 가며 읽습니다. 따라서 모든 입력 파일을 동시에 열어야 합니다. 이는 bash에서 가능하지만 쉘은 이러한 종류의 처리에 적합한 도구가 아닙니다. 큰 입력 파일의 경우 C로 작성하면 더 나은 결과를 얻을 수 있습니다. 또한 코드에 더 나은 구조를 부여하고 프로세스를 완전히 제어하는 것이 더 쉽습니다.