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

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

我正在编写一个解析制表符分隔文件的 bash 脚本。如果文件包含“提示”一词,脚本应要求用户输入一个值。

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

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

注意:该脚本应在 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"

输出:

$ ./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 '' ]]

示例 tsv 文件:

$ cat promptTest.tsv
something       else
prompt
otherthing       nelse

答案1

最简单的方法是用作/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

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

更一般地说,您可以根据原始标准输入获取一个新文件句柄,然后从中读取。注意该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

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

% ./y
We read the line: hello
is this correct?
yes
You responded yes

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

% echo yes | ./y
We read the line: hello
is this correct?
You responded yes

答案2

此 SO 问答题为:如何在 Bash 中读取文件或标准输入?显示了这个方法,它强调了如何做听起来像您正在寻找的事情:

while read line
do
  echo "$line"
done < "${1:-/dev/stdin}"

答案3

您可以在进行重定向之前复制标准输入。

#!/bin/bash
# Assuming here fd 4 is unused.  Dup file descriptor 0 (stdin) to
# file descriptor 4
exec 4<&0 

while read x; do # Read from stdin (the file b/c of redirect below)
    echo "From $1: $x"
    read y <&4 # Read from file descriptor 4 (the original stdin)
    echo "From keyboard: $y"
done < "$1"

相关内容