2012-07-28 46 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