将变量传递给 awk

将变量传递给 awk

我有一个巨大的文件需要分成多个文件。

我正在使用split,效果很好

file=home/sap/dim/deltafile.D2017313.T100058932IDL.gz

gunzip -c ${file} | split -l 10000000 -d -a 4 - ${file%/*}/"working".$v_procid.`basename ${file%.*}`.part.

有了awk它也能工作。但是当我传递变量时awk,它失败了。

gunzip -c ${file} | awk 'NR%10000000==1 {x="F" ++i} {print > x}'  

awk创建名为F1, F2...的文件

我需要使用变量,并且尝试了所有不同的示例。没有运气。

答案1

您可以将数据传递给awkwith -v var=value,可以存在任意数量的 -v 选项:

awk -v foo=FOO 'END {print foo}' </dev/null
awk -v foo=FOO -v bar=BAR 'END {print foo, bar}' </dev/null

像往常一样,您还可以使用 shell 变量等作为赋值的一部分:

awk -v bar="$PWD" 'END {print bar}' </dev/null

file=home/sap/dim/deltafile.D2017313.T100058932IDL.gz
awk -v bar="${file%/*}" 'END {print bar}' </dev/null

答案2

在外部构造文件名的静态部分awk并将其传递给awk变量:

prefix="${file%/*}/working.$v_procid.$(basename ${file%.*}).part"

gunzip -c "$file" |
awk -v p="$prefix" 'NR % 10000000 == 1 { f = p "" ++i } { print >f }'

f = p "" ++i位可以替换为f = sprintf("%s%s", p, ++i)

如果您希望生成大量输出文件,则可能需要close()在写入下一个输出文件之前显式显示前一个文件,这样您就不会意外用完可用的文件描述符:

awk -v p="$prefix" 'NR % 10000000 == 1 { if (f) close(f); f = p "" ++i } { print >f }'

答案3

对前两个答案还有一点要补充。还有第二种传递变量的方法,即在指定程序后将它们添加到命令行。

awk program.awk /path/to/input var=value second/input

来自GNU Awk 手册

文件名参数和变量赋值参数之间的区别是在 awk 即将打开下一个输入文件时进行的。在执行过程中,它会检查文件名以查看它是否确实是变量赋值;如果是这样,awk 设置变量而不是读取文件。

因此,在读取所有先前指定的文件后,变量实际上会收到给定值。特别是,以这种方式分配的变量值在 BEGIN 规则内不可用(请参阅 BEGIN/END),因为此类规则在 awk 开始扫描参数列表之前运行。

所以虽然

awk -v var=value program.awk

允许您在任何 BEGIN 部​​分之前传递程序开始的值,如果需要,您还可以随时更改程序变量。

相关内容