小知识: awk 命令之投影与变量

469 阅读2分钟

小知识,大挑战!本文正在参与「程序员必备小知识」创作活动

前文我们用到了awk最基础的应用。也就是对输入的每一行按列处理,每一列的内容会被映射到$n上,然后交给我们使用。

awk的列默认是以空白符分割的,但是我们也可以使用-F 指定分割符号,比如说,我们要读取一个csv文件的前两列可以像下面这样

echo "1,2,3"|awk -F, '{ print $1,$2 }'

用echo假装了输入的文件内容。运行结果是1 2 。

甚至它还可以按多个分割符号进行分割,只需要把-F值得的分割符号改成多个,比如像下面这样

echo "1;3,2,3"|awk -F '[,;]' '{ print $1,$2,$3 }'

其实这部分已经很强了,因为它实际上是我们在关系代数中的一个非常重要的操作:"投影"。或者说函数式计算的map操作。

但是awk不仅仅止步于此,它还有更厉害的地方。

awk 不仅仅是可以在每一行做操作,它还可以在运行开始和结束执行一些操作。

更关键的是,awk是支持自定义变量的 (变量支持数字和字符串)。

比如最简单的应用,统计文件第2列的值的平均数。

假设我们的文件长这样

a 3
b 5
c 4
d 11

假设我们把它存到的data.txt

然后我们像下面这样

cat data.txt | awk '{sum+=$2}END{printf("平均值:%.2f\n", sum/NR)}'

在awk中的语法是这样的,主要有三个部分,分别是开始,结束,和每一行需要运行的。我们省略了开始。只使用了每行和结束。

对于每一行我们加上了它的第二列的值。这里sum这种变量在awk中如果没有做初始化,那么它默认会是0或者空字符串。所以我们也就没有写BEGIN部分,而是直接在每行的运行内容上直接使用了变量。

如果需要让程序更清晰可以写成这样(可读性更好一些)。

cat data.txt|awk 'BEGIN{sum=0}{sum+=$2}END{printf("平均值:%.2f\n", sum/NR)}'

在每行的运行完成之后,就到了END部分程序的执行,其中NR是表明处理过的行数,也就是记录数量,这是awk自带的变量,另外在这里我们使用了一个和先前不一样的函数,printf。它和C语言类似用于格式化输出。与print相比,换行符之类的就需要我们手动输出了。

最终的输出结果是:

平均值:5.75

awk执行隐式地以行单位的操作,让我们可以专注地处理每一行的数据。而它提供的变量机制则进一步增强了它的功能性。使得除了投影操作之外,我们还可以做一些类似数据统计的操作。