Io-Redirection
通過 bash 輸入重定向為多個 read(stdin) 呼叫提供輸入
假設我們有以下程序,它呼叫
read()
了兩次:#include <stdio.h> #include <unistd.h> #define SIZE 0x100 int main(void) { char buffer1[SIZE]; char buffer2[SIZE]; printf("Enter first input: \n"); fflush(stdout); read(STDIN_FILENO, buffer1, SIZE); printf("Enter second input: \n"); fflush(stdout); read(STDIN_FILENO, buffer2, SIZE); printf("\nFirst input:\n%s", buffer1); printf("\nSecond input:\n%s", buffer2); return 0; }
當我們直接呼叫它時,我們可以輸入
1
第一個輸入和2
第二個輸入以便列印:First input: 1 Second input: 2
使用輸入重定向時如何實現這一點?
以下方法不起作用,因為第一個
read
消耗兩個輸入:管道重定向:
$ { echo "1"; echo "2"; } | ./main_read Enter first input: Enter second input: First input: 1 2 Second input:
Heredoc重定向:
$ ./main_read << EOF 1 2 EOF Enter first input: Enter second input: First input: 1 2 Second input:
假設原始碼不能更改,並且輸入有時必須短於
SIZE
.有什麼方法可以指示第一個
read()
停止閱讀,以便第二個read()
消耗其餘的輸入?
這可能無法為您提供可接受的解決方案,但考慮到:
- >
原始碼不能更改
- shell 不能更改正在執行的程序的打開文件描述符指向的位置,也不能使正在執行的程序停止從文件描述符中讀取
您剩下的一些替代方案(沒有利用競爭條件)是:
- 嘗試確保您的程序始終
SIZE
一次輸入字節:{ echo foo | dd bs=256 conv=sync echo bar | dd bs=256 conv=sync } 2>/dev/null | ./main_read
輸出:
Enter first input: Enter second input: First input: foo Second input: bar
這至少假設它
SIZE
小於管道緩衝區的大小。
- 將程序的呼叫包裝在
expect
(或等效的)腳本中:expect <<'EOT' spawn ./main_read expect "Enter first input:" send "foo\n" expect "Enter second input:" send "bar\n" expect eof EOT
或者,以允許您將其他命令的輸出通過管道傳輸到它的方式,單獨讀取(假設您的作業系統為程序提供
/dev/fd/n
文件描述符):echo foo | { echo bar | expect 4<&0 <<'EOT' spawn ./main_read set chan [open "/dev/fd/3"] gets $chan line expect "Enter first input:" send "$line\r" close $chan set chan [open "/dev/fd/4"] gets $chan line expect "Enter second input:" send "$line\r" close $chan expect eof EOT } 3<&0
在這兩種情況下,輸出都是:
spawn ./main_read Enter first input: foo Enter second input: bar First input: foo Second input: bar
- 在允許以非阻塞方式打開管道的系統(例如 Linux)上,您可以使用 FIFO 使 shell 讀取和寫入您的程序。例如:
makefifo fifo { exec 3<>fifo ./main_read 0<&3 } | sh -c ' # read a line from the pipe # read from a file or a different pipe, write to fifo # repeat ... # echo the output from the pipe ' mysh
雖然,如果
expect
您可以使用,我認為沒有令人信服的理由更喜歡重新發明它。但是請注意,正如其他人所指出的那樣,不能保證您的所有程序
read
s 實際上都會獲得SIZE
字節。