2010-06-04 58 views
6

我有一個劇本,抓住標準輸入:在Perl中,如何確定是否存在標準輸入?

&process_input 

sub process_input { 
    while(<STDIN>) { 
     $log_data .= $_; 
    } 
} 

當我運行該腳本:

myscript.pl -param1=a -param2=b 

我會停留在這個子程序。一切運行正常,如果我做的:

echo "" | myscript.pl -param1=a -param2=b 

的問題是我如何確定我連在放一個標準?我會認爲while()會返回false並且不會運行,但是我猜測它實際上正在等待您鍵入某種爲什麼會被「卡住」的內容。

+1

可能重複[如何判斷STDIN是否連接到Perl終端?](http://stackoverflow.com/questions/528781/how-can-i-tell-if-stdin-is-connected -in-a-terminal-in-perl) – Ether 2010-06-04 20:20:15

回答

18

你想要做的是檢查你的STDIN(標準輸入)來自哪裏:另一個應用程序或終端。在你的情況下,這是第二種選擇,導致讀操作阻止進程直到用戶輸入內容。有關解決方案,請參閱How can I tell if STDIN is connected to a terminal in Perl?

if (-t STDIN) { 
    # input attached to terminal and will probably ask user 
} else { 
    # input from other process 
} 

還有IO::Interactive可能會做得更好/更可靠的檢查。

+0

謝謝!由於該腳本也可以由另一個應用程序運行,因此我可以執行-t選項。 – EDJ 2010-06-04 18:22:52

2

聲明<STDIN>只有按下控制檯上的「enter」後纔會返回。如果你想解決這個問題,我相信你可以使用IO::Handle來換行STDIN,並且調用$stdin->blocking(0)來啓用非阻塞IO。

+2

問題不在於阻止IO,而是''(相當於'readline(* FILEHANDLE)')正在尋找一行輸入。它不會返回,直到找到'\ n'(好吧,技術上來說,是輸入記錄分隔符$ /'的一個實例)。手柄是否阻塞並不重要。另外,如果你使用'IO :: Handle',你可以簡單地在現有的全局句柄上使用它的方法:'STDIN-> blocking(0);' – daotoad 2010-06-04 19:11:03

1

這很正常。如果沒有輸入文件作爲參數給定,unix工具的標準用法是使用STDIN。嘗試catlessgrep,等等。這是給調用者提供輸入,如果只

tool < /dev/null 

我強烈建議不要嘗試,以確定是否「輸入」可用,因爲它會帶來問題,無論你如何實現這個。特別是,避免-t,因爲在需要時僞造終端會有問題。相反,依靠更傳統的界面。

如果您希望能夠將任何輸入傳遞給您的工具,那麼您首先會使用STDIN會很奇怪。通常會使用可選的參數。

tool --foo file 
tool --foo <(echo "") 

另一個選擇是要求用戶告訴你什麼時候沒有輸入。

tool --batch 

爲了幫助您解決界面的設計問題,它確實有助於瞭解您的工具的功能。

0

當用戶鍵入Ctrl + D,即文件字符的結尾時,程序將繼續。

相關問題