Io-Redirection
用 POSIX 加入兩個未排序的文件?
因為
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
打開它們時,它將從兩個sort
s 中讀取。您可以通過一些 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 不會分叉)。