awk中创建子进程

在使用awk过程中越发觉得awk强大!

有这样一个任务,输入文件(in.txt)是一个无序的多行文本,格式如下:

baidu       www.baidu.com/     7
net114      www.net114.com     NULL
soufun      zzbbs.soufun.com           202.108.253.30
baidu       www.baidu.com/     8
miibeian    www.miibeian.gov.cn        110.85.5.15
baidu       www.baidu.com/     1
baidu       www.baidu.com/     2
net114      www.net114.com     122.11.51.71
miibeian    www.miibeian.gov.cn        8.5.1.74
baidu       www.baidu.com/     3
... ...

每行3列,列之间用 \t 分隔。

需求是:将in.txt按照第一列切分成多个文件,并要求输出文件有序。

对于这个需求,第一想到的做法是用awk将文件拆分,然后再对输出的几个文件排序。

这样做OK,但有点小问题:awk将in.txt拆分后,再进行排序,就会占用2倍的磁盘空间,因为原始文件占一份磁盘空间,排序后的文件也要占一份磁盘空间。

然后考虑的是直接在awk里通过pipe直接输出给sort进行排序,这样就只占用一份空间了,代码大致如下:

cat in.txt | awk -F'\t' '{ print $2"\t"$3 | "sort > out."$1".sorted"; }'

我这样将代码写完后想到了一个问题:对于上面这段代码,awk内部会开几个子进程呢?

因为对于我的输入(in.txt), 通过awk切分后 print 那条管道命令会变成多条,如:

第1行输入: print "www.baidu.com  \t  7" | " sort > out.baidu.sorted"
第2行输入: print "www.net114.com  \t  122.11.51.71" | " sort > out.net114.sorted"
... ...
第4行输入: print "www.baidu.com/  \t  8" | " sort > out.baidu.sorted"
... ...

看上面几行:
* 对于第1行,awk启动了一个子进程,执行的命令是: “sort > out.baidu.sorted”;
* 第2行,awk应该启动另一个子进程,执行的命令是: “sort > out.net114.sorted”;
* 第4行,现在问题来了:执行的命令还是: “sort > out.baidu.sorted”, 那对于awk来说,是会新启一个子进程还是用第1行启的子进程呢?

我们把awk脚本简单修改下,通过pstree来看看就知道了.

修改后的awk命令:
cat in.txt | awk -F'\t' '{ print $2"\t"$3 | "sort > out."$1".sorted"; system("sleep 3"); }' &
让脚本后来处理,并且每输出一行sleep 3sec.

然后看看awk到底创建了几个子进程:
$ pstree -a | grep -C10 "cat"
  |   |           |-awk -F\t {\040print\040$2"\t"$3\040|\040"sort\040>\040out."$1".sorted";\040system("sleep\0403");\040}
  |   |           |   |-sh -c sort\040>\040out.baidu.sorted
  |   |           |   |   `-sort
  |   |           |   |-sh -c sort\040>\040out.net114.sorted
  |   |           |   |   `-sort
  |   |           |   |-sh -c sort\040>\040out.soufun.sorted
  |   |           |   |   `-sort
  |   |           |   |-sh -c sort\040>\040out.miibeian.sorted
  |   |           |   |   `-sort
  |   |           |   `-sleep 3

从pstree显示的结果看来,awk对于相同的命令只启动了一个子进程。

再查了下awk手册,里面的说法也确定了我的观察结果:

NOTE: If using a pipe or co-process to getline, or from print or printf within a loop, you must use close() to create new instances of the command. AWK does not automatically close pipes or co-processes when they return EOF.

Leave a Comment


*


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>