読み取りで駆動されるwhileループで読み取りをヒントとして使用しますか?

読み取りで駆動されるwhileループで読み取りをヒントとして使用しますか?

各反復の開始時に複数の変数を読み取り、ループへのユーザー入力を読み取る必要があるユースケースがあります。

考えられる解決策を探る方法がわかりません。

  1. 割り当てには標準入力ではなく別のファイルハンドルを使用してください。
  2. for代わりにループを使用してください...ループ内に複数の変数を割り当てる... | while read ...方法がわかりませんfor

    echo -e "1 2 3\n4 5 6" |\
    while read a b c; 
    do 
      echo "$a -> $b -> $c";
      echo "Enter a number:";
      read d ;
      echo "This number is $d" ; 
    done
    

ベストアンサー1

read私が正しくしている場合は、基本的に値のリストを繰り返してから、ループ内で別の値を繰り返したいと思います。

ここにはいくつかのオプションがあります。 1と2はおそらく最も賢いでしょう。

1. 文字列を使用した配列シミュレーション

2D配列を持つことは良いですが、Bashでは不可能です。値にスペースがない場合のおおよその回避策は、3つの数値の各セットを文字列に貼り付けてから、ループ内で文字列を分割することです。

for x in "1 2 3" "4 5 6"; do 
  read a b c <<< "$x"; 
  read -p "Enter a number: " d
  echo "$a - $b - $c - $d ";
done

もちろん、for x in 1:2:3 ...などの他の区切り文字を使用することもできますIFS=: read a b c <<< "$x"


2. パイプを無料の標準入力にリダイレクトする別のパイプと交換します。

もう1つの可能性は、別のfdから読み込み、read a b cそのfdに直接入力することです(標準シェルで動作する必要があります)。

while read a b c <&3; do
    printf "Enter a number: "
    read d
    echo "$a - $b - $c - $d ";
done 3<<EOF
1 2 3
4 5 6
EOF

コマンドからデータをインポートするには、ここでプロセス置換を使用することもできます。 (while read a b c <&3; ...done 3< <(echo $'1 2 3\n4 5 6')プロセス置換はbash/ksh/zshの機能です。)


3. stderrからユーザー入力を受け取る

または、代わりに例のようなパイプを使用しますが、ユーザー入力がパイプソースの代わりに(fd 2)から出るようにreadします。stderrstdin

echo $'1 2 3\n4 5 6' |
while read a b c; do 
    read -u 2 -p "Enter a number: " d
    echo "$a - $b - $c - $d ";
done

読み取りはstderr少し奇妙ですが、実際には対話型セッションで頻繁に機能します。 (/dev/tty実際にリダイレクトをバイパスしたい場合は、明示的に開くこともできます。これは、lessデータがパイプで接続されていてもユーザーの入力を取得するために使用されるものと似ています。)

stderrただし、このように使用すると、すべての場合に機能するわけではなく、代わりに外部コマンドを使用している場合は、read少なくともそのコマンドに複数のリダイレクトを追加する必要があります。

また見てください私の変数が1つの「読み込み中」ループではローカルですが、一見似ている他のループではローカルではないのはなぜですか?いくつかの関連する質問があります... | while


4. 必要に応じてアレイの一部をスライスします。

通常の1D配列のスライスをコピーして2D配列を近似することもできると思います。

data=(1 2 3 
      4 5 6)

n=3
for ((i=0; i < "${#data[@]}"; i += n)); do
    a=( "${data[@]:i:n}" )
    read -p "Enter a number: " d
    echo "${a[0]} - ${a[1]} - ${a[2]} - $d "
done

変数の名前が必要な場合は、etc${a[0]}になどを割り当てることもできますがabZshはもっとうまくいくでしょう。

おすすめ記事