【发布时间】:2014-07-14 00:22:56
【问题描述】:
有没有办法计算和记录通过管道的参数数量?我正在从长度未知的文件中传输值。我可以使用 tee 将数字转储到 STDOUT,但不能将它们放入变量中:
seq 10 | tee >(wc -l) | xargs echo
我感兴趣的是这对于美学和我自己的理解是否可行,而不是一些迂回的替代方案,例如重新扫描(非 txt)file_of_unknown 长度两次,或写入实际文件然后读回,等等。
谢谢!
【问题讨论】:
有没有办法计算和记录通过管道的参数数量?我正在从长度未知的文件中传输值。我可以使用 tee 将数字转储到 STDOUT,但不能将它们放入变量中:
seq 10 | tee >(wc -l) | xargs echo
我感兴趣的是这对于美学和我自己的理解是否可行,而不是一些迂回的替代方案,例如重新扫描(非 txt)file_of_unknown 长度两次,或写入实际文件然后读回,等等。
谢谢!
【问题讨论】:
管道中的组件(例如 OP 中的tee)在子shell 中执行。因此,它不能修改父 shell 的变量。这是关于子shell 和shell 变量的一般规则。每个 shell 都有自己的变量;当(子)shell 启动时,父 shell 的(部分)变量被复制到子 shell,但父 shell 中的变量与子 shell 中的变量之间没有链接。
您可以使用管道在子外壳之间进行通信,但在管道中您已经在这样做了,因此很难协调另一层,尽管这并非不可能。不过,美学不是很好。
所以基本上你最好的方法就是你明确放弃的那个,“写入一个实际的文件然后读回”。这既简单又可靠,而且速度非常快,尤其是当文件位于内存中的临时文件系统上时(请参阅tmpfs)。
顺便说一句,xargs 通常会在空白处拆分输入行以生成参数,因此通常它接收的参数数量与它读取的行数不同。
【讨论】:
这是你要找的吗?
sh$ seq 10 | tee >(wc -l > /tmp/f) | xargs echo; V=$(cat </tmp/f)
1 2 3 4 5 6 7 8 9 10
sh$ echo $V
10
如果您不喜欢使用临时文件(我应该使用 mktemp...),可以使用 fifo (mkfifo) 代替吗?
如果可以使用 stderr 作为输出,您可以将示例重写为:
sh$ V=$(seq 10 | tee >(xargs echo 1>&2) | wc -l)
1 2 3 4 5 6 7 8 9 10
sh$ echo $V
10
【讨论】: