使用 T 恤和粘贴进行工艺替代

使用 T 恤和粘贴进行工艺替代

我试图通过其他两个命令的输出来传输命令,然后合并两个进程替换的结果。一个让我接近的例子是:

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

要求(示例)
粘贴输出

  1. sed -rn '/3/ s/[^ ]* ([^ ]*).*/\1/'
    仅选择带有“3”的行并获取第二个字段。
    这些是第一个数字为 1、13、22 和 28 的行
  2. 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

相关内容