在使用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.
Recent Comments