如何在while循环中读取用户输入的每一行?

7
我有一个Bash文件,会提示用户输入一些参数,并在没有任何输入时使用默认值。然后,该脚本将使用这些参数执行其他命令。这一切都很顺利,直到最近加入的部分。
为了从txt文件中读取NAMES参数,我添加了一个while循环以接收文件中的名称,但我仍想提示输入剩余参数。
但是一旦添加了while循环,输出显示get_ans()中的打印提示,但不会暂停读取操作,因此所有默认值都被选中。
我想从文件中读取第一个参数,然后从提示用户输入的所有后续文件中获取参数。
为什么添加while循环会导致出现问题?
cat list.txt | 
while read line
do 
  get_ans "Name" "$line"
  read NAME < $tmp_file

  get_ans "Name" "$line"
  read NAME < $tmp_file
done

function get_ans
{
  if [ -f $tmp_file ]; then
    rm $tmp_file

  PROMPT=$1
  DEFAULT=$2

  echo -n "$PROMPT [$DEFAULT]: "
  read ans
  if [ -z "$ans" ]; then
    ans="$DEFAULT"
  fi
  echo "$ans" > $tmp_file
}

(注意:代码不可复制粘贴,请见谅错别字。实际代码在主函数之前定义)

在决定是否接受之前,我建议您先查看其他答案(其中一个告诉您如何解决问题,而不仅仅是问题是什么)。 - Charles Duffy
3个回答

4
你可以将数据通过管道输入到while循环的标准输入流中。所以在get_ans函数中的read也是从该标准输入流中获取数据。
为了避免这个问题并停止使用临时文件,你可以将数据通过不同的文件描述符输入到while中。
while read -u 9 line; do
   NAME=$(get_ans Name "$line")
done 9< list.txt

get_ans() {
    local PROMPT=$1 DEFAULT=$2 ans
    read -p "$PROMPT [$DEFAULT]: " ans
    echo "${ans:-$DEFAULT}"
}

3

如果你在*NIX机器上(而非Windows机器),想要直接从终端读取,而不是从标准输入中读取,请使用以下命令:

while read foo</some/file; do
    read bar</dev/tty
    echo "got <$bar>"
done

1

当你在命令行中将一个命令管道传递到另一个命令中时,例如:

$ foo | bar

Shell会设置这样一个环境,使得bar的标准输入来自于foo的标准输出。任何foo发送到stdout的内容都将直接传递给bar的stdin。

在您的情况下,这意味着您的脚本只能从cat命令的标准输出中读取,该输出将包含您文件的内容。

不要在命令行上使用管道,而是将文件名作为脚本的第一个参数。然后在代码中打开并从文件中读取,并像往常一样从用户那里读取。


好的,我已经移除了管道并使用了while read line; do ... done < $1,但它仍然跳过输入读取。 - c card

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接