今天群里有人问了个问题:
grep ...|awk ... filename
这种情况下awk先将管道|的数据处理完后,再开始处理文件filename么?
答案很多人都知道是否定的,
一般的格式是:grep ...filename|awk ...
不过问题目的人是想实现这样的功能:
grep ... file1 | awk ... file2
将grep后的结果送给awk先存下来,再处理file2
大致的需求是明白了
问题大于awk在有文件参数的情况下是忽视标准输入的(见下边的源码分析)
所以解决的方法有下边几个
1:awk ... <(grep ... file1) file2
2:grep ... file1 | awk ... - file2
下边是关于awk源码读取输入的分析:
main函数在进行参数,初始化后,调用do_input()读取输入
Do_input使用while循环,处理“每个输入”
while ((iop = nextfile(FALSE)) != NULL) {}
其中nextfile函数调用iop_open打开文件
Iop_open函数里有么一段:
if (STREQ(name, "-"))
openfd = fileno(stdin);
else if (do_traditional)
goto strictopen;
strictopen:
if (openfd == INVALID_HANDLE)
openfd = open(name, flag, 0666);
即对待-,是去读取输入的
再回头来看看参数解析过程,
在main函数里进行解析输入文件参数: srcfiles_add(CMDLINE, argv[optind]);
实际上是个宏定义:
#define srcfiles_add(stype, val) /
add_src(&srcfiles, &numfiles, &allocfiles, stype, val)
往一个数据结构里去增加一个元素,一个元素代表一个输入文件
并上上述的next_file中去遍历
static long i = 1;//初始i为1
static int files = FALSE;
for (; i < (long) (ARGC_node->lnode->numbr); i++) {…
files = TRUE;}// ..里调用lookup去查找文件,找到时,files会置为true
if (files == FALSE) {
files = TRUE;
/* no args. -- use stdin */
/* FNR is init'ed to 0 */
根据files为false判断无输入文件参数(包括-),即默认读取stdin做为输入
结论:
Awk:读取输入的几种方式
1:没有指定输入文件,即读取标准输入(通常采用管道实现)
2:有输入文件,就不读取标准输入(除非指定-)
3:如果有输入文件,又想读取标准输入,可以用-,即为开头的例子