如何从管道中使用STDIN两次

时间:2017-06-21 08:55:31

标签: linux bash shell awk pipe

我有一个类似

的awk脚本
awk 'FNR==NR {col1[$1]++; col2[$2]++; next} {print $0, col2[$2] "/" length(col1)}' input input

但是如果我有很多文件,需要将这个脚本用于连接文件,如:

cat *all_input | awk 'FNR==NR {col1[$1]++; col2[$2]++; next} {print $0, col2[$2] "/" length(col1)}' STDIN STDIN

不起作用。如何从管道中使用STDIN两次?

3 个答案:

答案 0 :(得分:4)

您不需要使用烟斗。如果您使用bash使用process-substitution as <(cmd),即实现重定向,其中进程的输入或输出(某些命令序列)显示为临时文件。

awk 'FNR==NR {col1[$1]++; col2[$2]++; next} {print $0, col2[$2] "/" length(col1)}' <(cut -f3 5- input) <(cut -f3 5- input)

答案 1 :(得分:2)

How to use STDIN twice from pipe的答案是“你不能”。如果你想要使用stdin中的数据两次,那么当你第一次读它时需要将它保存到某个地方,这样你下次就可以使用它。例如:

$ seq 3 |
awk '
    BEGIN {
        if ( ("mktemp"|getline line) > 0) tmp=line; else exit
        ARGV[ARGC]=tmp; ARGC++
    }
    NR==FNR { print > tmp }
    { print FILENAME, NR, FNR, $0 }
' -
- 1 1 1
- 2 2 2
- 3 3 3
/var/folders/11/vlqr7jmn6jj3fglyl12lj0l00000gn/T/tmp.Y03l9pS7 4 1 1
/var/folders/11/vlqr7jmn6jj3fglyl12lj0l00000gn/T/tmp.Y03l9pS7 5 2 2
/var/folders/11/vlqr7jmn6jj3fglyl12lj0l00000gn/T/tmp.Y03l9pS7 6 3 3

或者您可以将其存储在内部数组或字符串中,稍后再从中读取。

话虽如此,您的具体问题并不需要任何花哨的东西,只需简单:

cat *all_input | awk 'FNR==NR {col1[$1]; col2[$2]++; next} {print $0, col2[$2] "/" length(col1)}' - *all_input

会这么做但除非您的文件非常庞大,否则您真正需要的是存储在阵列中的方法:

awk '{ col1[$1]; col2[$2]++; f0[NR]=$0; f2[NR]=$2 }
END {
    for (nr=1; nr<=NR; nr++) {
        print f0[nr], col2[f2[nr]] "/" length(col1)
    }
}' *all_input

答案 2 :(得分:0)

我不知道这是否有帮助因为我不是awk专家,但任何Linux应用程序(包括awk)都可以直接从 / proc / self / fd / 0 读取stdin

请注意,这比open(0)更不便携,只能在具有可读procfs的Linux上运行(几乎所有的Linux发行版)。

如果应用程序允许并行文件描述符消耗,则可以打开该文件描述符两次并从中读取两次。

路径中的

self 指定访问应用程序的PID。