AWK - 列に関する質問

AWK - 列に関する質問

質問があります。私はこれを自分で把握しようとしましたが、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を読む必要があるからです。残念ながら、他の方法は思い出せませんでした。

  1. 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. 一時ファイルをすべて削除

関連情報