如何在bash中切换文件输入和终端输入

wca*_*art 3 bash shell

我正在编写一个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
Run Code Online (Sandbox Code Playgroud)

但是,目前我认为脚本认为我正在尝试从与、和answer相同的输入文件中读入。如何在文件输入和终端输入之间切换?abc

Cha*_*ffy 5

如果您的标准输入已从文件重定向(即,您是使用 调用的./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
Run Code Online (Sandbox Code Playgroud)

如果您想exec 3</dev/tty从顶部跳过(/dev/tty在脚本开头仅打开一次,允许稍后使用 TTY 进行读取<&3),那么您可以改为编写:

read -r answer </dev/tty
Run Code Online (Sandbox Code Playgroud)

...每次要从终端执行读取时打开它。但是,您希望确保对循环中在这些情况下失败的情况进行错误处理(例如,如果此代码是从 cron 作业运行的,则调用时将命令ssh作为参数传递,并且no ,或没有-tTTY 的类似情况)。


或者,考虑在 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
Run Code Online (Sandbox Code Playgroud)

  • 总是富有洞察力,并且总是有一些有价值的东西可以添加到 bash 工具箱中。 (2认同)