iru*_*var 11 shell io-redirection file-descriptors process-substitution
这是我最常做的运行grep,并wc在一个文件,而无需扫描两次
<file.txt tee >(grep LITERAL) >(wc -l) >/dev/null
Run Code Online (Sandbox Code Playgroud)
然而,这会产生
EXEC LITERAL
32
Run Code Online (Sandbox Code Playgroud)
有时和
32
EXEC LITERAL
Run Code Online (Sandbox Code Playgroud)
在其他时间。(第一个实例中grepfrom的输出先于from的输出,wc在第二个实例中反之亦然。)
另一方面,使用重定向和文件描述符
{ { <file.txt tee /dev/fd/3 | grep LITERAL >&4; } 3>&1 | wc -l ;} 4>&1
Run Code Online (Sandbox Code Playgroud)
我似乎总是得到
EXEC LITERAL
32
Run Code Online (Sandbox Code Playgroud)
我更喜欢输出顺序是可预测的,但是第二种方法可以保证吗?
同时
<file.txt tee >(grep LITERAL) >(wc -l) >/dev/null
Run Code Online (Sandbox Code Playgroud)
和:
{ { <file.txt tee /dev/fd/3 | grep LITERAL >&4; } 3>&1 | wc -l ;} 4>&1
Run Code Online (Sandbox Code Playgroud)
所有tee、grep和wc都是同时启动的。重要的是最后会发生什么。
wc仅当在标准输入上看到文件结尾时才会打印结果。在第一种情况下,那就是tee退出的时候,因为然后tee将关闭正在读取的fd管道的另一端(由进程替换启动)。wc无法保证grep到那时会读取其所有输入,更不用说写入其输出(假设管道可以容纳相当大量的数据,并且wc可能会比 更快grep)
在第二种情况下,wc当正在读取的管道的所有写入者都关闭了管道的末尾时,将看到文件结束。但在这种情况下,有几个作家。tee(通过其 fd 打开/dev/fd/3并通过其 fd 3)并且grep其fd3 也向管道打开wc(尽管它没有任何使用它,更不用说写入它了)。内部{可能会导致一个额外的子 shell 进程,该进程也将打开fd3 并等待tee和grep。
这意味着只有在退出wc后才会写入其行号。grep
如果您以正确的方式编写它,即关闭不需要打开的 fd:
{ { <file.txt tee /dev/fd/3 4>&- |
grep LITERAL >&4 3>&- 4>&-; } 3>&1 | wc -l 4>&-;} 4>&1
Run Code Online (Sandbox Code Playgroud)
那么在优化子 shell 进程的 shell 中就无法保证顺序。然而,据我所知,唯一的 shell 是ksh93使用ksh93管道的套接字对,所以/dev/fd/3至少在 Linux 上不起作用。
要查看正在运行的进程,您可以替换grep为ps:
$ { { <file.txt tee /dev/fd/3 4>&- | ps -H >&4 3>&- 4>&-; } 3>&1 | wc -l 4>&-;} 4>&1
PID TTY TIME CMD
8727 pts/5 00:00:00 bash
8815 pts/5 00:00:00 bash
8817 pts/5 00:00:00 tee
8818 pts/5 00:00:00 ps
8816 pts/5 00:00:00 wc
Run Code Online (Sandbox Code Playgroud)
使用bash,您可以看到额外的 shell 进程,并且您可以看到它还在 fd 3 上打开了管道:
$ (p=$BASHPID; { { <file.txt tee /dev/fd/3 4>&- | lsof -ag "$p" -d3 >&4 3>&- 4>&-; } 3>&1 | wc -l 4>&-;} 4>&1)
COMMAND PID PGID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 9843 9842 chazelas 3w FIFO 0,8 0t0 153304 pipe
tee 9845 9842 chazelas 3w FIFO 0,8 0t0 153304 pipe
lsof 9846 9842 chazelas 3r DIR 0,3 0 1 /proc
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
487 次 |
| 最近记录: |