bash:读取文件时提示用户输入

Ber*_*enz 5 bash stdin read

我正在处理一个解析制表符分隔文件的 bash 脚本。如果文件包含单词“prompt”,脚本应该要求用户输入一个值。

似乎在读取文件时,“读取”命令无法从标准输入读取,因为“读取”被简单地跳过。

有没有人可以解决从文件和标准输入中读取的问题?

注意:该脚本应在 Git Bash 和 MacOS 上运行。

下面是一个失败的小代码示例:

#!/bin/bash

#for debugging
set "-x"


while IFS=$'\r' read -r line || [[ -n "$line" ]]; do
  [[ -z $line ]] && continue

  IFS=$'\t' read -a fields <<<"$line"

  command=${fields[0]}

  echo "PROCESSING "$command
  if [[ "prompt" = $command ]]; then
    read -p 'Please enter a value: ' aValue
    echo
  else 
    echo "Doing something else for "$command
  fi
done < "$1"
Run Code Online (Sandbox Code Playgroud)

输出:

$ ./promptTest.sh promptTest.tsv
+ IFS=$'\r'
+ read -r line
+ [[ -z something       else ]]
+ IFS=' '
+ read -a fields
+ command=something
+ echo 'PROCESSING something'
PROCESSING something
+ [[ prompt = something ]]
+ echo 'Doing something else for something'
Doing something else for something
+ IFS=$'\r'
+ read -r line
+ [[ -z prompt ]]
+ IFS=' '
+ read -a fields
+ command=prompt
+ echo 'PROCESSING prompt'
PROCESSING prompt
+ [[ prompt = prompt ]]
+ read -p 'Please enter a value: ' aValue
+ echo

+ IFS=$'\r'
+ read -r line
+ [[ -n '' ]]
Run Code Online (Sandbox Code Playgroud)

示例 tsv 文件:

$ cat promptTest.tsv
something       else
prompt
otherthing       nelse
Run Code Online (Sandbox Code Playgroud)

Ste*_*ris 6

最简单的方法是用作/dev/tty键盘输入的读取。

例如:

#!/bin/bash

echo hello | while read line
do
  echo We read the line: $line
  echo is this correct?
  read answer < /dev/tty
  echo You responded $answer
done
Run Code Online (Sandbox Code Playgroud)

如果您不在终端上运行它,并且不允许将输入重定向到程序中,则会中断,但在其他方面工作得很好。

更一般地说,您可以根据原始标准输入获取一个新文件句柄,然后从中读取。注意该exec线和read

#!/bin/bash

exec 3<&0

echo hello | while read line
do
  echo We read the line: $line
  echo is this correct?
  read answer <&3
  echo You responded $answer
done
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,程序看起来都有点像:

% ./y
We read the line: hello
is this correct?
yes
You responded yes
Run Code Online (Sandbox Code Playgroud)

第二种变体还允许重定向输入

% echo yes | ./y
We read the line: hello
is this correct?
You responded yes
Run Code Online (Sandbox Code Playgroud)