Io-Redirection

用 POSIX 加入兩個未排序的文件?

  • January 26, 2017

因為join必須對輸入進行排序,所以命令的呼叫通常類似於:

join <(sort file1) <(sort file2)

這不是可移植的,因為它使用 POSIX 未指定的程序替換。

join也可以通過指定-為文件參數之一來使用標準輸入。但是,這只允許通過管道對其中一個文件進行排序:

sort file1 | join - <(sort file2)

似乎應該有一種簡單的方法來完成兩個文件的排序,然後僅使用 POSIX 指定的功能來連接結果。也許使用重定向到第三個文件描述符的東西,或者它可能需要創建一個 FIFO。但是,我無法將其視覺化。

如何join在未排序的文件上使用 POSIXly?

您可以使用兩個命名管道(當然也可以使用一個命名管道和標準輸入):

mkfifo a b
sort file1 > a &
sort file2 > b &
join a b

程序替換基本上是通過設置這些 fifo 來工作的(/dev/fd/在可用的情況下使用而不是命名管道)。例如,在 bash 中:

$ echo join <(sort file1) <(sort file2)
join /dev/fd/63 /dev/fd/62

請注意 bash 如何用文件名替換程序,在/dev/fd. (不過/dev/fd/,足夠新版本的 zsh、bash 和 ksh93 將使用命名管道。)在呼叫 時,它們保持打開狀態join,因此當join打開它們時,它將從兩個sorts 中讀取。您可以通過一些 lsof-trickery 看到它們通過:

$ sh -c 'lsof -a -d 0-999 -p $$; exit' <(sort file1) <(sort file2)
COMMAND  PID    USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
sh      1894 anthony    0u   CHR  136,5      0t0      8 /dev/pts/5
sh      1894 anthony    1u   CHR  136,5      0t0      8 /dev/pts/5
sh      1894 anthony    2u   CHR  136,5      0t0      8 /dev/pts/5
sh      1894 anthony   62r  FIFO   0,10      0t0 237085 pipe
sh      1894 anthony   63r  FIFO   0,10      0t0 237083 pipe

(這exit是為了防止一種常見的優化,即當只有一個命令要執行時,shell 不會分叉)。

引用自:https://unix.stackexchange.com/questions/340391