行数が異なる3つのファイルがあります。 3つのファイルを繰り返しながら、各ファイルの最初の行を新しいファイルoutput1.txtとして印刷し、各ファイルの2行目を別の新しいファイルoutput2.txtとして印刷しようとしています。各ファイルには行数が異なるため、file2 と file3 のエントリを持たない複数の行がある場合は、それを無視して、後で生成される出力ファイルに何も印刷しないでください。 Bashでどのようにこれを達成できますか?
ファイル1
xyz
abc
def
ghi
jkl
ファイル2
123
456
789
ファイル3
ax1
by2
結果ファイル
出力1.txt
xyz
123
ax1
出力2.txt
abc
456
by2
出力3.txt
def
789
出力4.txt
ghi
出力5.txt
jkl
ベストアンサー1
bash
これを行うには、Tellを使用してくださいawk
。これが bash の目的です(たとえば、テキスト処理自体を実行する代わりに)。
たとえば、次のawk 1行ステートメントは、FNR
リテラル文字列「output」、現在の入力ファイルの現在の行番号(awk変数)、およびリテラル文字列「.txt」で構成されるファイル名に各入力行を書き込みます。
$ awk '{print > "output" FNR ".txt"}' file*
$ tail output*
==> output1.txt <==
xyz
123
ax1
==> output2.txt <==
abc
456
by2
==> output3.txt <==
def
789
==> output4.txt <==
ghi
==> output5.txt <==
jkl
注:出力ファイルの数が多い(数百以上)、問題が発生する可能性があります。一部のバージョンのawkでは、カーネルおよびログイン環境でプロセスに許可されているファイルハンドルの数を超えると、プロセスがエラーで終了する可能性があります。異なるバージョンのawk(GNU awkなど)を使用すると、特定の瞬間に書き込み用に開いているファイルハンドルを管理するときに遅くなる可能性があります。入力ファイルの一部が数百行の長さでない限り、これは問題ではありません。
以下は、すべてのバージョンのawkとすべての長さの入力ファイルで動作しますが(一度に書き込むために1つの出力ファイルのみを開くため)、はるかに遅くなります。なぜなら各書き込みの出力ファイルを開き、書き込み後すぐに閉じます。それにもかかわらず、シェルで実行するよりも数倍速いです。
awk '{
# use 5-digit zero-padded output filenames for this version
# e.g. output00001.txt
out = sprintf("output%05i.txt", FNR);
if (out in files) {
# we have written to this file before, so append to it
print >> out
} else {
# first write to this file, so create or truncate it.
print > out
files[out]=1
}
close(out)
}' file*