awk:(有条件的)打印到 gzip 的管道输出

use*_*413 3 command-line bash awk

考虑这个文件:

#!/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
Run Code Online (Sandbox Code Playgroud)

在下面的脚本中,我根据第一列中的值(第一列中的值已经排序)对这个文件的行进行分组,并将每个组打印到一个单独的 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");}'
Run Code Online (Sandbox Code Playgroud)

如何将结果打印到压缩流"output/"varn"_"$1".gz"(而不是未压缩的 txt 文件"output/"varn"_"$1".txt")?

(因此所需的输出与现在脚本生成的输出相同,只有我希望输出的文件被压缩并保存到.txt.gz而不是像代码现在那样的纯文本文件)。

(我尝试gzip >{print}块内使用但无济于事:(

(PS 我有点像 awk 菜鸟,所以这个问题可能是一个非常愚蠢的问题。)

mur*_*uru 7

您可以通过管道传输到 GNU awk 中的命令print。从GNU awk 手册

print items | command
Run Code Online (Sandbox Code Playgroud)

可以通过管道而不是文件将输出发送到另一个程序。此重定向打开一个管道到命令,并通过此管道将项目的值写入为执行命令而创建的另一个进程。

重定向参数command实际上是一个 awk 表达式。它的值被转换为一个字符串,其内容给出了要运行的 shell 命令。例如,以下生成两个文件,一个未排序的人名列表,以及一个按字母倒序排序的列表:

awk '{ print $1 > "names.unsorted"
       command = "sort -r > names.sorted"
       print $1 | command }' mail-list
Run Code Online (Sandbox Code Playgroud)

所以:

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";}'
Run Code Online (Sandbox Code Playgroud)

例如:

% echo 1 2 | awk '{print $2 | "gzip > "$1".gz"}'
% zcat 1.gz 
2
Run Code Online (Sandbox Code Playgroud)