从 awk 读取完整管道输入

从 awk 读取完整管道输入

据我了解,awk 可以通过两种方式使用。您可以将文件列表作为参数传递给它,也可以在管道中使用它。我尝试将它与文件列表作为参数一起使用,因此BEGINEND块仅对所有文件执行一次。但我有一个问题,我的文件需要先解密,然后才能将它们传递给 awk。所以我对管道进行了以下设置:

find . -name "*.gpg" -exec sh -c "gpg -d {} | awk -f process.awk" \;

现在,每个文件都会执行BEGINENDprocess.awk,这不是我想要的。有没有办法解密传递给 awk 的文件,以便这些块只执行一次?更新:因为我还需要文件名,所以process.awk我认为最好单独获取文件内容,但是这样就违反了我对所有找到的文件执行一次的要求,对吗BEGINEND

答案1

假设您的文件名不包含换行符:

while IFS= read -r fname; do
    gpg -d "$fname"
done < <(find . -name '*.gpg') |
awk -f process.awk

要执行您现在所说的操作并将每个文件名传递给 awk,最简单的事情可能是(假设 bash 4.* forreadarraymapfile以其他方式编写一个循环来填充fnames[]):

readarray -t fnames < <(find . -name '*.gpg')
for fname in "${fnames[@]}"; do
    gpg -d "$fname" |
    awk -v fname="$fname" -v tot="${#fnames[@]}" -v nr="$((++nr))" -f process.awk
done

这样你就有了每个文件名,你可以在和部分中fname测试是否执行代码:nr==1BEGINnr==totEND

BEGIN {
    if (nr==1) {
        do BEGIN stuff
    }
}
{ do common stuff }
END {
    if (nr==tot) {
        do END stuff
    }
}

或者,如果您有临时文件的空间,您可以循环调用gpg并将所有输出写入同名文件的临时目录中,并对每个文件调用 awk ,而不必进行更改process.awk

tmpdir=$(mktemp -d) &&
while IFS= read -r fname; do
    gpg -d "$fname" > "$tmpdir"/"$fname"
done < <(find . -name '*.gpg') &&
awk -f process.awk "$tmpdir"/* &&
rm -rf "$tmpdir"

相关内容