假设我有一个包含以下内容的文件:
1,2,3,4
我可以使用awk像这样处理该文件;
awk -v FS="," '{print $1}' file1
此外,我可以使用Here String调用awk,这意味着我从stdin中读取:
awk -v FS="," '{print $1}' <<<"9,10,11,12"
命令1产生结果1
,命令2
按预期产生9。
现在说我有第二个文件2:
4,5
如果我用awk后续解析这两个文件:
awk -v FS="," '{print $1}' file1 file2
我明白了:
1
4
正如所料。
但是,如果我正在混合stdin 和读取文件的读取,那么我从stdin读取的内容将被忽略,只有文件中的内容会按顺序处理:
awk -v FS="," '{print $1}' file1 file2 <<<"9,10,11,12"
awk -v FS="," '{print $1}' file1 <<<"9,10,11,12" file2
awk -v FS="," '{print $1}' <<<"9,10,11,12" file1 file2
所有三个命令都会产生:
1
4
这意味着来自stdin的内容只会被丢弃。现在shell在做什么?
有趣的是,如果我将命令3更改为:
awk -v FS="," '{print $1}' <<<"9,10,11,12",file1,file2
我只是得到9
,这是有意义的,因为file1 / 2只是stdin的两个字段。但那为什么呢?
awk -v FS="," '{print $1}' <<<"9,10,11,12" file1 file2
未扩展为
awk -v FS="," '{print $1}' <<<"9,10,11,12 file1 file2"
还会产生结果9
?
为什么来自stdin的内容会被忽略?对命令1和2也出现了同样的问题。在这里做了什么shell?
我尝试了以下命令:GNU bash,版本4.2.53(1)-release
答案 0 :(得分:1)
文件的标准输入和输入不能很好地混合在一起。此行为不是awk
独有的,您可以在许多命令行应用程序中找到它。如果你这样想是合乎逻辑的:
需要逐个处理文件。消费应用程序无法控制STDIN后面的输入何时开始和停止。看echo a,b,c | awk -F, '{print $1}' file1 file2
。需要以什么顺序读取传入的“文件”?当您考虑何时需要重置FNR
或FILENAME
应该是什么时,很明显很难做到这一点。
您可以玩的一个技巧是让awk
(或任何其他程序)从shell生成的文件描述符中读取。 awk -F, '{print $1}' file1 <(echo 4,5,6) file2
将首先完成您的预期。
这里发生的是,使用<(...)
语法(例如:/proc/self/fd/11
)创建了正确的文件描述符,并且读取程序可以将其视为文件。这是第二个参数,所以它是第二个文件。 FNR
和FILENAME
都清楚它们应该是什么。