我正在编写一个从文件中读取的bash
脚本。从文件中读取后,我想提示用户输入,并从终端读取它。
这是我的代码的摘录:
while IFS=',' read -r a b c
do
#a, b, c are read in from file
data1=$a
data2=$b
data3=$c
#later in the loop
#answer should be read in from the terminal
echo "Enter your answer to continue:"
read answer
done
但是,目前我认为该脚本认为我试图从与answer
,a
和b
相同的输入文件中读取c
。如何在文件和终端输入之间切换?
答案 0 :(得分:4)
如果您的stdin已从文件重定向(即,您使用./yourscript <file
调用),则使用/dev/tty
从终端读取:
#!/bin/bash
exec 3</dev/tty || {
echo "Unable to open TTY; this program needs to read from the user" >&2
exit 1
}
while IFS= read -r line; do # iterate over lines from stdin
if [[ $line = Q ]]; then
echo "Getting input from the user to process $line" >&2
read -r answer <&3 # read input from descriptor opened to /dev/tty earlier
else
echo "Processing $line internally"
fi
done
如果您想跳过顶部的exec 3</dev/tty
(在脚本开头只打开/dev/tty
一次,允许稍后使用<&3
从TTY读取) ,那么你可以写一下:
read -r answer </dev/tty
...每次要从终端执行读取时打开它。但是,您希望确保在循环中在这些情况下失败的情况下进行错误处理(例如,如果此代码是从cron作业运行的,则ssh
调用作为参数传递的命令没有-t
,或者 没有TTY的类似情况。)
或者,考虑在除stdin之外的描述符上打开文件 - 这里,我们使用文件描述符#3进行文件输入,并假设调用为./yourscript file
(stdin指向终端):
#!/bin/bash
filename=$1
while IFS= read -r line <&3; do # reading file contents from FD 3
if [[ $line = Q ]]; then
echo "Getting input from the user to process $line" >&2
read -r answer # reading user input by default from FD 0
else
echo "Processing $line internally" >&2
fi
done 3<"$filename" # opening the file on FD 3