我试图通过其他两个命令的输出来传输命令,然后合并两个进程替换的结果。一个让我接近的例子是:
command | tee >(sed -rn 's/.*foo (bar).*/1/p') >(awk '{print $3}')
但是,我想实现以下目标:
- 我不需要查看原始命令的输入流
- 我想使用“粘贴”来合并结果
我想一种选择是运行两个单独的命令并将它们放入文件中,但这并不像我想要的那么优雅。在 bash 中执行此操作最优雅的(单行,清楚理解)方法是什么?
答案1
您看到原始命令的输出的原因是因为tee
输出stdout
以及指定的文件。要放弃它,您可以将此输出放在>/dev/null
命令末尾,或通过添加额外的 将此输出重定向到您的进程替换之一>
,例如:
command | tee >(sed -rn 's/.*foo (bar).*/1/p') > >(awk '{print $3}')
或者更简单,只需使用另一个管道:
command | tee >(sed -rn 's/.*foo (bar).*/1/p') | awk '{print $3}'
至于使用 组合两个进程替换的结果paste
,除非有一些我不知道的晦涩的 shell 技巧,否则没有办法在不使用命名管道的情况下做到这一点。最终这是两行(为了清晰起见,格式化为更多):
mkfifo /tmp/myfifo
command |
tee >(sed -rn 's/.*foo (bar).*/1/p' >/tmp/myfifo) |
awk '{print $3}' |
paste /tmp/myfifo -
如果您将其放入脚本中,还可以考虑使用创建临时命名管道的建议这里。
答案2
您只需在sed
.
command |
sed '/\([^ ][^ ]* *\)\{2\}/{h
s///;s/^ *//;s/ .*/p
g};s/.*foo \(bar\).*/\1/p;d'
但至于另一件事,你有tee
大约文件|pipe
:
cmd1 | {
{ tee /dev/fd/3 |
cmd2 >&2
} 3>&1 |
cmd3
} 2>&1 |paste
但既然你已经在使用了,sed
你可以像使用它一样使用它聪明的 tee
并且仅在必须时才进行复制/重定向:
cmd | {
sed -n 'p;s/.*foo \(bar\).*/\1/w /dev/fd/3' |
awk ...
} 2>&1
答案3
恕我直言,它更优雅(清楚地理解),避免了“技巧” tee
。
@mikeserv 已经显示了一个sed
命令,您也可以“粘贴”到里面awk
。
命令替换为命令的示例printf
:
$ printf "foo %s %s %s\n" {1..30}
foo 1 2 3
foo 4 5 6
foo 7 8 9
foo 10 11 12
foo 13 14 15
foo 16 17 18
foo 19 20 21
foo 22 23 24
foo 25 26 27
foo 28 29 30
要求(示例):
粘贴输出
sed -rn '/3/ s/[^ ]* ([^ ]*).*/\1/'
仅选择带有“3”的行并获取第二个字段。
这些是第一个数字为 1、13、22 和 28 的行awk 'NR>2 {print $3}'
显示所有行的第三个字段
来自需求 1 的流被捕获到数组中bar
,
来自需求 2 的流被捕获到数组中secondstream
。
处理完所有输入后,将捕获的流粘贴到 END 块中。
printf "foo %s %s %s\n" {1..30} |
awk '/3/ {bar[barcounter++]=$2}
NF>2 {secondstream[streamnr++]=$3}
END {for (i=0;i<streamnr;i++) print bar[i], secondstream[i];}
'
结果:
1 2
13 5
22 8
28 11
14
17
20
23
26
29