タブ区切りファイルを解析する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
最も簡単な方法は、/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
2番目のバリエーションでは、入力をリダイレクトすることもできます
% echo yes | ./y
We read the line: hello
is this correct?
You responded yes
これは、SO Q&Aタイトル: Bashでファイルまたはstdinから読み取る方法? は、探しているように聞こえる方法を強調するこのメソッドを示しています。
while read line
do
echo "$line"
done < "${1:-/dev/stdin}"
リダイレクトを行う前に、標準入力を複製できます。
#!/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"