今天羣裏有人問了個問題:
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:如果有輸入文件,又想讀取標準輸入,可以用-,即爲開頭的例子