質問があります。私はこれを自分で把握しようとしましたが、awk
それを機能させるにはあまりにも新しいようです。
ファイル(Database.txtなど)があるとします(値はタブで区切られています)。
NA64715 YU24921 MI84612 MI98142 NA94732
3241531 4957192 4912030 6574918 0473625
0294637 9301032 8561730 8175919 8175920
9481732 9359032 8571930 8134983 9385130
9345091 9385112 2845830 4901742 3455141
別のファイル(たとえばpopulations.txt
)には、どのIDがどのグループに属しているかについての情報が含まれています。たとえば、次のようになります。
NA64715 Europe
YU24921 Europe
MI84612 Asia
MI98142 Africa
NA94732 Asia
私がすべきことは、awk
すべてのグループ(ヨーロッパ、アジア、アフリカ)の列を含む別々のファイルを強制的に生成することです。処理するファイルが大きいため、単に列数を数え、番号を付けて、簡単な方法で処理することはできません。どのIDがどの人口(ヨーロッパなど)に属しているかを確認し、データベースawk
ファイルで特定の列を見つけて、列全体を新しいファイル(すべての人口に対して別々)にコピーする必要があります。
結果は次のようになります。
ファイル 1( europe.txt
):
NA64715 YU24921
3241531 4957192
0294637 9301032
9481732 9359032
9345091 9385112
ファイル2(asia.txt
)
MI84612 NA94732
4912030 0473625
8561730 8175920
8571930 9385130
2845830 3455141
ファイル3(africa.txt
)
MI98142
6574918
8175919
8134983
4901742
誰でもこの問題を解決するのに役立ちますか?
答え1
これはファイルを一度にナビゲートし、ファイル全体をメモリに保存する必要はありません。各宛先ファイルに対して開かれたファイル記述子を保持します。
awk -F '\t' '
NR==FNR {population[$1]=$2; next}
FNR==1 {
for (i=1; i<=NF; i++) {
destination[i] = population[$i] ".txt"
}
}
{
delete separator
for (i=1; i<=NF; i++) {
printf "%s%s", separator[destination[i]], $i > destination[i]
separator[destination[i]] = FS
}
for (file in separator) {
printf "\n" > file
}
}
' populations.txt database.txt
答え2
私はこれが最善のアプローチではないと思います。なぜなら、私たちが持っている地域に1を加えただけに何度もDatabase.txtを読む必要があるからです。残念ながら、他の方法は思い出せませんでした。
Database.txtを置き換えます:
awk '{for(i=1;i<=NF;i++){a[NR,i]=$i}}NF>p{p=NF}END{for(j=1;j<=p;j++ ){str=a[1,j];for(i=2;i<=NR;i++){str=str" "a[i,j];}print str}}' データベース.txt > データベース.tmp
もっと読みやすい(同じコマンド):
awk '
{
for (i=1; i<=NF; i++) {
a[NR,i] = $i
}
}
NF>p { p = NF }
END {
for(j=1; j<=p; j++) {
str=a[1,j]
for(i=2; i<=NR; i++){
str=str" "a[i,j];
}
print str
}
}' database.txt > database.tmp
2. idsを含むファイルを読み込み、転置されたDatabase.tmpからすべてのIDをgrepします。
while read id region ; do grep -m 1 $id database.tmp >> $region.txt.tmp ; done < population.txt
3. すべての Region.txt.tmp ファイルを必要な形式に置き換えます。
for region_file in *txt.tmp ; do awk '{for(i=1;i<=NF;i++){a[NR,i]=$i}}NF>p{p=NF}END{for(j=1;j<=p;j++){str=a[1,j];for(i=2;i<=NR;i++){str=str" "a[i,j];}print str}}' $region_file > ${region_file%.tmp} ; done
4. 一時ファイルをすべて削除