コマンドからファイルのリストを読み取り、ユーザーに各ファイルの入力を要求しようとします。 1つはファイル名を読み取るのに使用されread
、もう1つはユーザー入力を取得するために使用されていますが、このスクリプトは無限ループに陥るようです。
foo () {
echo "a\nb\nc" | while read conflicted_file;
do
echo $conflicted_file
while true; do
read -e -p "> " yn
case $yn in
[nN]* ) echo "success"; break;;
[yY]* ) echo "fail"; break;;
* ) echo "invalid input";;
esac
done
done;
}
foo
外部レイヤーを削除するとwhile read
トリックを実行しているようです。どんなアイデアがありますか?
答え1
read
標準入力から読み取るので、両方ともread
標準入力で開いた同じパイプを介して出力から読み取られます。echo
read
パイプの外側の stdin からループ内を読み取るには、次のようにします。
foo () {
printf 'a\nb\nc\n' |
while IFS= read -r conflicted_file; do
printf '%s\n' "$conflicted_file"
while true; do
IFS= read <&3 -re -p "> " yn
case $yn in
[nN]* ) echo "success"; break;;
[yY]* ) echo "fail"; break;;
* ) echo "invalid input";;
esac
done
done
} 3<&0
つまり、foo
関数本体全体のfd 3にコピーします。
答え2
「読み取り」操作は、ttyの代わりにパイプから読み取りを試みます。これにはいくつかの解決策があります。
- ランニング
read ... </dev/tty
。これは、foo()関数が入力リダイレクトを期待しない限り機能します。 パイプを別のファイル記述子にリダイレクトし、そのファイル記述子を繰り返して、内部読み取り呼び出しが影響を受けないようにします。
それは次のとおりです。
exec 3< <(echo "a\nb\nc") while read -u 3 conflicted_file; do ... read -e -p "> " yn ... done exec 3>&-