我有一组非常复杂的命令:
command | ... | ... | tee >(grep -c '[^3]$') >(grep -c '[^35]$') 1>/dev/null
我不想有一个临时文件来保存输出,因为它非常大。我尝试>(grep -c '[^3]$' | read variable)
这样做,>(grep -c '[^3]$' | read variable2)
但我想由于进程替换的子 shell 调用,位不起作用。
我该如何将输出直接传送到多个变量?有可能吗?
现在我有这个解决方法:
var=$(command ... | ... | ... | tee >(grep -c '[^3]$') >(grep -c '[^35]$') 1>/dev/null)
var1=$(tail -1 <<< $var)
var2=$(head -1 <<< $var)
但我认为它很笨拙而且看起来不太好。我知道我可以 grep 到另一个文件中,但我也不喜欢它。
提前致谢。
答案1
使用awk
, 而不是tee
-ing 来替换两个 grep 进程。例如:
command | ... | ... | awk '
/[^3]$/ { c1++; next };
/[^35]$/ { c2++; next };
END { print c1, c2 > counts.txt }'
read var1 var2 < counts.txt
rm counts.txt
如果你不想使用临时文件,你可以这样做:
read var1 var2 < <(command | ... | ... | awk '
/[^3]$/ { c1++; next };
/[^35]$/ { c2++; next };
END { print c1, c2 }')
答案2
首先,您将命令链中的标准输出发送到/dev/null
,因此您的分配可能会分配一个空值。删除它。看起来您正试图仅捕获输出的第一行和最后一行;这在一行中可能很棘手,但awk
应该能够处理它:
var="$(command ... | [...] | tee [...] | awk 'NR==1{print $0} END { print $0}')"
然而,管道是简单的生物。它们有一个输入和一个输出。您不能(轻松)使用管道将数据发送到多个位置。你能得到的最接近的是使用命名的管道,本质上是您试图避免的临时文件(技术上不正确;先进先出队列与文件不同,但我正在简化)。