2,000個の列を含む大容量ファイルから複数の列をインポートする

2,000個の列を含む大容量ファイルから複数の列をインポートする

2000列のLinuxシステムの大容量ファイルから複数の特定の列をインポートしたいと思います。どうすればいいですか?

file1.gz ファイルは次のようになります。

0 0 0 0 0 0 0 0 0 0 ...
0 0 0 0 0 0 0 0 0 0 ...
0 0 0 0 0 0 0 0 0 0 ...
0 0 0 0 0 0 0 0 0 0 ...
0 0 0 0 0 0 0 0 0 0 ...
0 0 0 0 0 0 0 0 0 0 ...
0 0 0 0 0 0 0 0 0 0 ...
0 0 0 0 0 0 0 0 0 0 ...
0 0 0 0 0 0 0 0 0 0 ...

file2にインポートする必要がある列は次のとおりです。

186
187
188
189
190
191
192
193
194
195
(about 1000 column)

ベストアンサー1

では、awk特定の列を番号で参照できます。たとえば、列12$12は列1345です$1345。また、デフォルトの列区切り文字は空白なので、スペースで区切られたファイルを使用する例では、解凍して目的の列をawk印刷するスクリプトを渡すだけです。

zcat file.gz | awk '{print $1,$12,$195} > newFile

ここで複雑なのは、必要な列が多すぎて印刷できないことです。ここでは、まず列を読んでから印刷する必要があります。

awk '{
        if (NR==FNR){ wantedColumns[NR]=$1 }
        else{ 
            for(i=1;i<=length(wantedColumns)-1;i++){ 
                printf "%s ", $(wantedColumns[i])
            }
            print $(wantedColumns[length(wantedColumns)])
        }
     }' file2 <(zcat file1.gz)

たとえば、

$ zcat file1.gz
line1_field1 line1_field2 line1_field3 line1_field4 line1_field5 line1_field6 
line2_field1 line2_field2 line2_field3 line2_field4 line2_field5 line2_field6 
line3_field1 line3_field2 line3_field3 line3_field4 line3_field5 line3_field6 
line4_field1 line4_field2 line4_field3 line4_field4 line4_field5 line4_field6 
line5_field1 line5_field2 line5_field3 line5_field4 line5_field5 line5_field6 
line6_field1 line6_field2 line6_field3 line6_field4 line6_field5 line6_field6 
line7_field1 line7_field2 line7_field3 line7_field4 line7_field5 line7_field6 
line8_field1 line8_field2 line8_field3 line8_field4 line8_field5 line8_field6 
line9_field1 line9_field2 line9_field3 line9_field4 line9_field5 line9_field6 

$ cat file2
2
4
5

このファイルに対して上記のスクリプトを実行すると、次のような結果が得られます。

$ awk '{
>         if (NR==FNR){ wantedColumns[NR]=$1 }
>         else{ 
>             for(i=1;i<=length(wantedColumns)-1;i++){ 
>                 printf "%s ", $(wantedColumns[i])
>             }
>             print $(wantedColumns[length(wantedColumns)])
>         }
>      }' file2 <(zcat file1.gz)
line1_field2 line1_field4 line1_field5
line2_field2 line2_field4 line2_field5
line3_field2 line3_field4 line3_field5
line4_field2 line4_field4 line4_field5
line5_field2 line5_field4 line5_field5
line6_field2 line6_field4 line6_field5
line7_field2 line7_field4 line7_field5
line8_field2 line8_field4 line8_field5
line9_field2 line9_field4 line9_field5
line10_field2 line10_field4 line10_field5

説明する

  • if (NR==FNR){ wantedColumns[NR]=$1 }NRは入力行番号、FNRは行番号現在のファイルの。 2 つは、最初のファイルを読み取る場合にのみ同じです。したがってNR、等しい場合はFNR最初のファイルを読み取ると、そのファイルの最初のフィールドはwantedColumnsインデックスが行番号で値がフィールドの配列に格納されます。
  • else { ... }:私たちのラーメンいいえ最初のファイルを読み込んでいます(今度は2番目のファイルにある場合)。
  • for(i=1;i<=length(wantedColumns)-1;i++){ NR:最初のインデックス(上のループで使用した値のために1です)から2番目のインデックスまで、目的の列の配列を繰り返し、各列を印刷してスペースを入れます。重要な警告:必ずしも元のファイルの列の順序を維持するわけではありません。列はの順に印刷されます file2。この順序が元のファイルの順序と異なる場合file2(たとえば、1 3 2代わりに存在する場合1 2 3)は、この順序で印刷されます。
  • print $(wantedColumns[length(wantedColumns)]):最後のフィールドを印刷し、その後に改行文字が続きます。
  • <(zcat file1.gz)bash:これは、コマンドの出力をファイルとして処理できるようにする["プロセス置換"][1]という機能(他の一部のシェルと同様)です。ここでは解凍されたファイルを使用し、zcatそれを2番目の入力「ファイル」にawk

この方法では、各行の末尾に余分なスペースを追加します。これが問題の場合は、sed最後に配管することで回避できます。

awk '...' | sed 's/ $//'

または、カンマで区切られたフィールドのリストにcut変更して、次のように渡すこともできます。file2cut

$ zcat file1.gz | cut -d' ' -f $(tr '\n' ',' < file2 | sed 's/,$//') 
line1_field2 line1_field4 line1_field5
line2_field2 line2_field4 line2_field5
line3_field2 line3_field4 line3_field5
line4_field2 line4_field4 line4_field5
line5_field2 line5_field4 line5_field5
line6_field2 line6_field4 line6_field5
line7_field2 line7_field4 line7_field5
line8_field2 line8_field4 line8_field5
line9_field2 line9_field4 line9_field5
line10_field2 line10_field4 line10_field5

説明する

  • zcat file1.gz |:解凍し、file1.gz内容を次のコマンドに渡します。
  • cut -d' ' cut:デフォルトタブ()の代わりにスペースを\tフィールド区切り文字として使用することを意味します。
  • -f $(tr '\n' ',' < file2 | sed 's/,$//'):印刷するフィールドを-f表示します。cutカンマで区切られたフィールドリストを使用できるため、tr '\n' ','すべての改行をコンマに変換して結果をフィールドリストに渡します。 [1]:https://www.gnu.org/software/bash/manual/html_node/Process-Substitution.html

おすすめ記事