web-dev-qa-db-ja.com

awk:(条件付き)印刷のパイプ出力をgzipに

このファイルを検討してください:

#!/usr/bin/env bash
cat > example_file.txt <<EOL
group, value
1, 3.21
1, 3.42
1, 3.5
2, 4.1
2, 4.2
EOL

次のスクリプトでは、このファイルの行を最初の列の値でグループ化し(最初の列の値は既にソートされています)、各グループを個々のtxtファイルに出力します。

var=$(echo 'example_file.txt')
var2=$(echo $var|sed "s/.txt//g")
mkdir -p output
cat $var | awk -v varn="$var2" -F, 'FNR == 1 {header = $0;next} !seen[$1]++ { print header > ("output/"varn"_"$1".txt") }{print > ("output/"varn"_"$1".txt");}'

質問

結果を圧縮ストリーム"output/"varn"_"$1".gz"(非圧縮のtxtファイル"output/"varn"_"$1".txt"ではなく)に出力する方法は?

(したがって、目的の出力はscripが現在生成するものと同じです。出力ファイルを圧縮して、現在のコードのようにプレーンテキストファイルではなく.txt.gzに保存したいだけです)。

gzip >ブロック内で{print}を使用しようとしましたが、使用できませんでした:(

(PS私はawk初心者なので、質問は本当にばかげているかもしれません。)

3
user2413

GNU awkのprintのコマンドにパイプできます。 GNU awkマニュアル :から

print items | command

ファイルにではなく、パイプを介して出力を別のプログラムに送信することができます。このリダイレクトにより、コマンドへのパイプが開かれ、コマンドを実行するために作成された別のプロセスにこのパイプを通じてアイテムの値が書き込まれます。

リダイレクト引数commandは、実際にはawk式です。その値は、その内容が実行されるシェルコマンドを提供する文字列に変換されます。たとえば、次の例では、2つのファイルが生成されます。1つは人の名前の未ソートリスト、もう1つはアルファベットの逆順にソートされたリストです。

awk '{ print $1 > "names.unsorted"
       command = "sort -r > names.sorted"
       print $1 | command }' mail-list

そう:

awk -v varn="$var2" -F, 'FNR == 1 {header = $0;next}
  !seen[$1]++ { print header | "gzip > "output/"varn"_"$1".gz" }
  {print | "gzip > output/"varn"_"$1".gz";}'

例えば:

% echo 1 2 | awk '{print $2 | "gzip > "$1".gz"}'
% zcat 1.gz 
2
6
muru