我正在编写一个解析制表符分隔文件的 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"