如何将一个命令的输出传递给多个命令?


20

使用流程替换或分组和管道,一个人可以将一组命令的输出(stdout)传递为另一条命令的输入。

范例:

wc < <(echo hi;echo bye)
(echo hi; bye) | wc

但是相反吗?

也就是说,有没有一种方法来发送一个命令的输出作为输入的许多其它命令在一个单行

就像是 :

cat testfile | wc | tail -n 5

不要从字面上看管道)。在这里,我试图通过输出cat testfile到两个wctail -n 5

另一个例子是:

获得句子的最后单词

echo "some random words"| wc -c | cut -f(out put of wc -c) (output of first echo)

Answers:


21

快速回答。您可以使用tee >(what_to_do) >(another_thing_to_do)您要执行的许多不同操作来继续执行命令。

例:

原始测试文件输出:

:~$ cat testfile.txt 
Device Model:     LITEONIT LCS-256M6S 2.5 7mm 256GB
Serial Number:    TW0XFJWX550854187616

输出并tee添加命令:

:~$ cat testfile.txt | tee >(tail -1) >(wc) >(awk '{print $3,$1,$2}')
Device Model:     LITEONIT LCS-256M6S 2.5 7mm 256GB
Serial Number:    TW0XFJWX550854187616
LITEONIT Device Model:
TW0XFJWX550854187616 Serial Number:
      2      10      91
Serial Number:    TW0XFJWX550854187616

tee中的每个命令都是您将在命令行上使用的普通命令,例如add in >(head -1 | wc)也可以。

:~$ cat testfile.txt | tee >(tail -1) >(head -1 | wc)  >(awk '{print $3,$1,$2}')
Device Model:     LITEONIT LCS-256M6S 2.5 7mm 256GB
Serial Number:    TW0XFJWX550854187616
      1       7      52
LITEONIT Device Model:
TW0XFJWX550854187616 Serial Number:
Serial Number:    TW0XFJWX550854187616

或者,您也可以通过awk$NF和一起使用来抓住最后一行的最后一句话wc

:~$ cat testfile.txt | tail -1 | tee >(wc) >(awk '{print $NF}')
Serial Number:    TW0XFJWX550854187616
TW0XFJWX550854187616
      1       3      39

注意:|管道命令添加到末尾可以覆盖命令中的多个命令tee。我在这里测试了一些示例:

示例1(管道命令提取所有最后的单词):

:~$ echo "This is just five words" | tee >(wc -l) >(wc -w) >(wc -c) | awk '{print $NF}'
words
24
5
1

示例2(不显示wc命令的输出。管道命令捕获第3个字。):

:~$ echo "This is just five words" | tee >(wc -l) >(wc -w) >(wc -c) | awk '{print $3}'
just

示例3(获取echo line的第三个单词。Tee命令。):

:~$ echo "This is just five words" | tee >(wc -l) >(wc -w) >(wc -c) >(awk '{print $3}')
This is just five words
just
24
5
1

示例4(获取echo行的最后一个单词。Tee命令。):

:~$ echo "This is just five words" | tee >(wc -l) >(wc -w) >(wc -c) >(awk '{print $NF}')
This is just five words
words
24
5
1

希望这可以帮助!


3
我喜欢T恤和咖啡!'-)
怪杰长老

1
关于各个使用者之间的输出排序的陈述tee是错误的。通常,您获得正确订单的原因是,在低负载计算机上,第一个使用者进程将首先运行。在较忙的机器上,第一个消费者可能在打印任何东西之前就进入了睡眠状态。
Matei David

@MateiDavid我无法证明这一点,所以我删除了声明。没关系
Terrance

2
看我的答案。但更重要的是,tee对消费者一无所知-他们是由bash谁来处理生产线的。所有bash要做的就是复制打开的文件描述符。除此之外,您还拥有多个使用方,它们正在写入在同一文件上打开的文件描述符。内核会解决这个问题,但是可以肯定的是,它们在bash命令行中出现的顺序不会成为一个因素。
Matei David

17

您需要tee将流分成几部分。尝试:

cat testfile | tee >(wc -l) >(wc -w) >(wc -c) | tail -n 5

笔记:

  • 如果多个进程(wctail)全部都写入标准输出:

    • 您可能会得到乱码的输出。

    • 无法保证其输出出现的顺序。要看到这一点,请尝试sleep 1; wc -w作为第二个消费者。

  • tee如果它的任何目的地没有足够快地消耗流,它将阻塞。意思是,将以大致类似的速度(以固定大小的缓冲为模)向目的地输入输入。对此没有简单的解决方法,唯一的选择是将流保存到文件中,并将其分别提供给使用者。对于wctail这不是问题。

最后,它更简单:

echo "some random words" | awk '{print $NF}'

5

moreutils软件包提供了pee准确地执行此命令的命令(合并管道和T形管,您怎么想?)。

对于第一个示例,您将使用:

cat testfile | pee wc "tail -n 5"

第二个示例更加复杂,因为您要将两个输入传递给最后一个命令。我可能会使用awk其他答案。

链接:https//joeyh.name/code/moreutils/

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.