列の数が異なるファイルをサブセットにし、出力に複数のファイルを作成する必要があります。ループでこれを実行しようとしていますが、イテレータは機能しません。
入力(タブ区切りフィールド)
abc 1
aaa 1
ccc 1
asd 2
sad 2
aaf 3
出力
ファイル1:
abc 1
aaa 1
ccc 1
ファイル2:
asd 2
sad 2
ファイル3:
aaf 3
私のテストはこれですが、空のファイルだけを出力します。
for i in $(seq 1 3); do awk -F "\t" '{$2 == $i}' input > cluster.$i.txt; done
答え1
コードが失敗する理由は、スクリプト$i
内でシェル変数を使用しようとしましたが、awk
間違って実行したためです。一重引用符内のテキストは'...'
シェルで文字通り処理されるため、$i
シェル変数の値ではなく2文字で処理されます$i
。また、比較をジョブとして実行しようとしています(つまり、行を印刷する暗黙のジョブがないことを意味します)。
値を渡すことができます。awk
awk -F $'\t' -v i="$i" '$2 == i' input > "cluster.$i.txt"
あるいは、各行をそれ自体の利点に従って処理し、awk
完全に回避することもできます。
while read field index
do
printf "%s\t%s\n" "$field" "$index" >> "cluster.$index.txt"
done < input
または、次をawk
使用して同じことを実行できます。
awk '{ fname = "cluster." $2 ".txt"; print > fname }' input
答え2
$i
シェル変数はawk式で内部的に参照されませんi
。コマンドラインを使用して変数を渡し、-v i="$i"
それをプレーンとして引用することができますi
。
{....}
また、行動一つでもない模様; modeがtrueのprint
ときにデフォルトの動作()を実行したいようです。$2 == i
だから
for i in $(seq 1 3); do
awk -F "\t" -v i="$i" '$2 == i'
input > cluster.$i.txt; done
ただし、インデックスごとに awk を 1 回呼び出す代わりに、次のことを検討することができます。
awk -F "\t" '{print > "cluster" $2 ".txt"}' input
入力を直接使用して$2
出力ファイル名を設定します。
空白文字のフィールド分割を特に回避したくない場合は、-F "\t"
awkがデフォルトのスペース区切り文字を削除して分割することを許可できます。