2012-07-28 60 views
4

如何在此while循環中編寫交互式響應代碼?bash:嵌套交互式讀取循環中也使用讀取

#!/bin/bash 

shows=$(< ${HOME}/.get_iplayer/tv.cache) 

# ... 
# ... stuff with shows omitted ... 
# ... 

function print_show { 
# ... 
    return 
} 

while read -r line 
do 
    print_show "$line" 

    read -n 1 -p "do stuff? [y/n] : " resp # PROBLEM 

# ... 
# resp actions omitted 
# ... 

done <<< "$shows" 

所以一個文件被讀取,「加工」,那麼結果行面向數據是在while read循環

使用,但while循環中讀取的行按預期不工作,那就是它不會等待用戶響應,可能是由於其封裝的while read上下文。

您能否建議如何解決這個問題或備用機制?

回答

4

你已經正確識別的原因是

while ...; do ...; done <<< "$shows" 

循環中,標準輸入被重定向,從而read不再從鍵盤讀取。

您可以通過使用非0的文件描述符來解決此問題;例如,

while read -r -u 3 line; do ...; done 3<${HOME}/.get_iplayer/tv.cache 

將使用FD 3的文件,而不是FD 0,允許正常read(不-u)使用原始標準輸入,或

while ...; do read -n 1 -p "do stuff? [y/n] : " -u 3 resp; done 3<&0 <<< "$shows" 

到原來的FD 0克隆到FD 3用您的字符串替換FD 0之前。

+0

非常感謝。這是完美的。 – Thorsen 2012-07-28 21:18:19

1

由於您已經將整個文件讀入內存,因此請將其讀入數組而不是單個字符串。

# Requires bash 4 or later 
mapfile -t loop_input < $HOME/.get_iplayer/tv.cache 

for line in "${loop_input[@]}"; do 
    print_show "$line" 
    read -n 1 -p "do stuff? [y/n] : " resp 
done 

如果仍然使用bash的早期版本,我還是建議你閱讀文件 到一個數組,而不是一個字符串,但它是不太方便。

declare -a loop_input 
while read; do loop_input+=("$REPLY"); done 

for line in "${loop_input[@]}"; do 
    ... 
done 

或者,你可以不讀所有文件到內存:

while read -u 3 line; do 
    .... 
done 3< $HOME/.get_iplayer/tv.cache 
+0

整潔,但請注意'mapfile'是在Bash 4中添加的。 – ephemient 2012-07-28 21:46:57

+0

謝謝。我會將其添加到我的工具包中。 – Thorsen 2012-07-28 22:43:44