最初の列に基づいて複数のUnixファイルを複数のファイルに分割する

最初の列に基づいて複数のUnixファイルを複数のファイルに分割する

複数のファイル(* data.txt)があり、列1の内容に基づいて各ファイルを複数のファイルに分割しようとしています。私はそれらを分割しましたが、$filename使用する出力ファイルの列1($ 1)を使用して名前を付ける方法がわかりませんprint。現在、次のコマンドの印刷は$1 ".txt"次の内容を提供します。代わりに、ENSG00000115232.txt file1_ENSG00000108094.txt, file1_ENSG00000115232.txt は各入力ファイルに対して個別の出力が必要なため、不適切です。私のコマンドは次のとおりです。"$b"予想される結果を得るには、このコマンドをどこで使用するのかわかりません。

for filename in *_data.txt
 do
    b=${filename%%_data.txt}
cat $filename | awk 'NR==1 {header = $0; next}!header_printed[$1]++ {print header > $1".txt"}{print > $1".txt"}'
done

ありがとうございます。

答え1

シェル変数をawkプログラムに渡す方法はいくつかあります。

  1. -vコマンドラインオプションを使用してください。

    awk -v b=${filename%data.txt} '... {print > (b $1 ".txt")}'
    
  2. awkプログラムの後に通常のパラメータに値を渡します。

    awk '... {print > (b $1 ".txt")}' b=${filename%data.txt}
    
  3. 値を渡してください。環境内部配列を介してENVIRONawkとしてアクセスします。

    b=${filename%data.txt} awk '... {print > (ENVIRON["b"] $1 ".txt")}'
    

ただし、「いくつかの」ファイルしかない場合は、シェルループを完全に省略し、すべてのワイルドカードファイルをawkに直接渡すことが合理的かもしれません。ここでは、FILENAME出力ファイルのプレフィックスを内部変数からエクスポートできます。例:

awk '
  FNR==1 {header = $0; b = FILENAME; sub(/data.txt$/,"",b); next}
  !header_printed[b $1]++ {print header > (b $1 ".txt")}
  {print > (b $1 ".txt")}
' *_data.txt

(サフィックスを使用splitまたはsubstr削除することもできます。シェル拡張に最も近い正規表現を使用しました。)data.txtsub${filename%data.txt}

関連情報