Files

使用標準輸出將標準輸入重定向到文件

  • January 19, 2017

所以我有一個程序可以接收使用者輸入並根據輸入輸出文本。

EDIT2:我想創建一個執行 C 執行檔的腳本,該腳本將 C 程序輸入從一個文件提供給並將輸出重定向到另一個文件。但是,每當為輸入列印輸出時,我也想列印輸入,基本上將輸入和輸出組合/合併在一起。所以我在一個文件中逐行輸入它,然後將每個輸入的輸出列印到一個文件中,我一直這樣做。我不想重新執行程序我希望程序在到達輸入文件的末尾或直到我從腳本向它發送終止信號之前仍然執行。(我正在嘗試為課程製作評分腳本。

Edit3:我不認為期望會起作用,因為我無法知道程序會輸出什麼。我只知道它應該接受什麼。例如,一個學生可能有一個程序說“給我一個字元:”,而另一個學生會說“輸入一個字元”,所以我不知道這些程序會發生什麼。

(注意:我將有許多不同的執行檔,它們有不同的格式,但都應該要求相同數量的輸入)

例如,執行檔之一可能是:

"Enter a number: " (Wait for user input)
"Give another: "  (Wait for user input
"Total: " (Output based on input)
"Do you want to run again? "(Wait for user input)

編輯:我的腳本的主要目標是執行程序,逐行從文件中獲取輸入。例如對於這個程序,我希望它把文件“輸入”作為標準輸入,但我也想跟踪與標準輸出合併的標準輸入。

所以我知道 ./a.out < input > output 會輸出

Enter a number: 
Give another:  
Total:  15
Do you want to run again? 

但是它缺少我想要包含的輸入,所以我可以通過查看輸出文件來判斷輸入是基於輸出的,因為輸入可能是 7 8 N 或 5 10 N 或類似的東西。

如果我理解正確,您想檢測何時a.out從標準輸入讀取數據,以及何時發送該數據並將該數據寫入同一日誌文件 stdout 被重定向到以echo互動方式執行時模擬終端的本地?

那麼也許一個解決方案(bash語法)會是這樣的:

mkfifo strace.fifo
{
 while read -d, trace; do
   if [[ $trace = *"read(0" ]]; then
     IFS= read -rn1 answer &lt;&3 || break
     answer=${answer:-$'\n'}
     printf %s "$answer" &gt;&2
     printf %s "$answer"
   fi
 done &lt; strace.fifo 3&lt; answers.txt |
   strace -o strace.fifo -e read ./a.out
} &gt; log 2&gt;&1

這個想法是使用strace(假設您在 Linux 上)跟踪read系統呼叫,並且只要read文件描述符為 0,就一次從answers.txt.

編輯:如果程序使用 stdio 或類似的東西。當輸出被重定向到一個正常文件並且不再是一個終端時,可能發生的事情是它輸出的所有提示都被緩衝,並且只會在程序退出時被刷新。

一種解決方法是使用stdbuf:替換./a.outstdbuf -oL ./a.out. 這將告訴應用程序(假設它是一個動態連結的應用程序並且緩衝是由於 stdio)在 stdout 上進行行緩衝,就好像它是一個終端一樣。但是,它仍然不會做的是在從 stdin 讀取 stdio 時刷新 stdout,就像在 stdin/stdout 是終端時通常會做的那樣。fflush因此,例如,在顯式或最終寫入換行符之前,不會顯示未被換行符終止的提示。所以最好可能是用來stdbuf -o0完全禁用緩衝。

如果a.out可以分叉程序或執行緒,請將-f選項添加到strace.

如果應用程序selectpoll實際執行read. 非阻塞 I/O 也可能導致我們發送數據過快。

如評論中所述。expect是模擬使用者互動的工具,它使用偽終端,因此您將自動獲取輸入回顯,並且不會出現緩衝輸出問題。作為 的替代方法stdbuf,您可以使用unbuffer它附帶的腳本來包裝a.out一個偽終端。在這種情況下,您可能希望在檢測讀取和發送答案之間添加一點延遲,以便expect在其標準輸出上重現提示。

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