awkを使用して500個のファイルをフィルタリングし、結果を単一のファイルに分類します。

awkを使用して500個のファイルをフィルタリングし、結果を単一のファイルに分類します。

私のディレクトリには何千ものファイルがありますが、フィルタリングしたいファイルには次の構文があります。*.imputed.*_info

awkを使用して、データの5番目の列値が0.50を超える各ファイルのレコードをフィルタリングしたいと思います。次の方法を使用できますawk '{if($5 >= .5) {print}}' filename

それも動作します。次に、500 個程度のファイル全体を繰り返しながら、この基準を満たす各ファイルのレコードを連結してみました。

以下を試しましたが、構文が正しくありません。

touch snplist.txt
for name in *.imputed.*_info; do
    snps="awk '{if($5 >= .5) {print}}' $name"
    cat snplist.txt "$snps" > snplist.txt
done

ベストアンサー1

コードは繰り返すたびに出力ファイルを上書きします。あなたも実際に電話をかけていませんawk

やりたいことは次のとおりです。

awk '$5 >= 0.5' ./*.imputed.*_info >snplist.txt

これにより、awkすべてのファイルが一度に呼び出され、シェルの拡張ワイルドカードパターン順序に従って1つずつ繰り返されます。ファイル内の行の5番目の列が0.5以上の場合、その行が出力されます(snplist.txt)。これは、条件に関連付けられたジョブ(ブロック)がない場合、デフォルトのジョブが{...}現在の行を出力するためです。

お持ちの場合大きいファイル数(千)が原因で、「パラメータリストが多すぎる」エラーが発生する可能性があります。この場合、以下を繰り返す必要があります。

for filename in ./*.imputed.*_info; do
    awk '$5 >= 0.5' "$filename"
done >snplist.txt

結果はawk変数に保存する必要はありません。ここでは出力されます。サイクル(したがって、ループ内のすべてのコマンド)はにリダイレクトされますsnplist.txt

何千ものファイルの場合は、awk各ファイルを個別に呼び出す必要があるため、非常に遅くなります。

作業を高速化するには、単一の呼び出しでファイルが多すぎる場合は、次の方法をawk使用することをお勧めします。xargs

printf '%s\0' ./*.imputed.*_info | xargs -0 awk '$5 >= 0.5' >snplist.txt

これにより、ファイル名のリストが生成され、printfnull で終わるリストに渡されます。xargsユーティリティxargsはそれを受け取りawk始めます。できるだけ一度、一括して。パイプライン全体の出力はにリダイレクトされますsnplist.txt

この回避策は、ユーザーがNULLで終わる入力を読み取るための非標準オプションを実装するコマンドを持つxargsLinuxなどのUnixを使用していると仮定します。また、シェルを使用しているとします。xargs-0bash組み込み printfユーティリティ(kshOpenBSDのデフォルトシェルには組み込みユーティリティがないため、ここでは機能しません)。


zshシェルの場合(つまり、ないbash):

autoload -U zargs
zargs -- ./*.imputed.*_info -- awk '$5 >= 0.5' >snplist.txt

これは基本的にロード可能なシェル関数をzargs再実装したものです。詳細については、(関数のロード後)とドキュメントを参照してください。xargszshzargs --helpzshcontrib(1)

おすすめ記事