を使用してファイルの最初の列の値に基づいてファイルを複数のファイルに分割したいのですが、zcat file2split.gz | awk '{print>$1}'
次のエラーが発生します。
awk: cmd. line:1: (FILENAME=file2split FNR=1666) fatal: can't redirect to `CCTGGCAG_GATATAAC_HAP1' (Operation not permitted)
どんなアイデアがありますか?ありがとうございます!
zipデータサイズは25Mbで、ここからダウンロードできます。 https://drive.google.com/file/d/1Qjq-ibdiyemBfuqpoC2h0VDhw09PS0ao/view?usp=sharing
答え1
現在の出力ファイル名が変更されるたびに古いファイル名を閉じると、開かれたファイル制限が発生するのを防ぎます。例えば
awk '{ out=$1;
if (out != lastfile) {
if (lastfile != "") { close(lastfile) };
lastfile = out
};
print > out'
ファイルを閉じて再度開くよりもはるかに優れています。すべて書く。最後に作成されてから名前が変更された場合にのみファイルを閉じます。ファイルがフィールド 1 でソートされると、ファイルを再度開く必要はありません。 「ほとんどソート」の場合、ファイルを再度開く必要はほとんどありません。
注:同じファイル名が複数回表示される場合隣接しないprint >> out
行がある場合は、代わりに出力を追加する必要がありますprint > out
。それ以外の場合、ファイルもう一度開く書き込みの場合、書き込み前に完全に上書きされます(つまり、ゼロサイズに切り捨てられます)。
(しかし、これが書き込み操作のたびにファイルが自動的に閉じられない理由の1つです。awk
もちろん、もう1つの主な理由は、そうしないと、同じファイルを書き込むたびに閉じて再開すると多くの時間がかかるためです。 。
awkスクリプトの特定の実行で初めてファイルを上書きし、同じ実行で同じファイルが再び表示された場合は、追加する場合は少し複雑です。例えば
awk '{ out=$1;
if (out != lastfile) {
if (lastfile != "") { close(lastfile) };
lastfile = out
};
if (seen[out]++) {
print >> out
} else {
print > out
}'
このバージョンでは、連想配列を使用して、seen
以前に特定のファイル名を見たことがないかどうかを追跡します。その場合は追加してください。それ以外の場合は上書きします。
答え2
あまりにも多くのファイルを同時に開いておくと、実際に現在の問題を引き起こしているかどうかは疑問です。しかし、参考にしたいことをする強力で効率的な方法は、GNU sort for-s
とawkを使用して次のことを行うことです。
zcat file2split.gz |
sort -s -k1,1 |
awk '
$1 != out {
close(out)
out = $1
}
{ print > out }
'
GNUソートがない場合は、次の標準のUnixツールのすべてのバージョンを使用して同じことを実行できます。
zcat file2split.gz |
awk -v OFS='\t' '{print NR, $0}' |
sort -k2,2 -k1,1n |
cut -f2- |
awk '
$1 != out {
close(out)
out = $1
}
{ print > out }
'
awkが出力ファイルの作成を開始する前に入力をソートする上記の方法を使用すると、awkは一度に1つの出力ファイルのみを開き、出力ファイルを複数回開く必要はありません。ただ開いて書くだけです。みんなラインを接続して閉じ、次の出力ファイルに移動します。