スペースで区切られた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番目の列)の値が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
これは本当に良い質問です。ファイルが3番目の列に基づいて昇順にソートされていると確信している場合は、SQL Worldのマージ結合に同様のアプローチを使用することをお勧めします。ファイルのソートは、bashで文字列を比較するために使用されるのと同じソート機能を使用して実行する必要があります。以下のスクリプトにはbashが必要です。以下を介して呼び出す必要があります。
$ script file1 file2 file3
3つの出力ファイル(file1.out、file2.out、file3.out)が生成されます。これには、すべての入力ファイルの3番目の列に値を持つ対応するソースファイルの行が含まれています。その値を持つすべての行は「.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で書くとより良い結果が得られます。また、コードにより良い構造を与え、プロセスを完全に制御する方が簡単です。