【Bash】while read 中の標準入力について【Shell】

while read 中にさらにwhile readなどを使うと最初のループの標準入力が内側でも使用されてしまう。
例)

#!/bin/bash
# readコマンドで list1.txt の内容を1行 PRM1 に受け取る
while read PRM1
do
    # PRM1の内容を表示
    echo "\$PRM1=[$PRM1]"

    # 標準入力をPRM2に受け取る。
    # (while read PRM1で標準入力を使っているため、
    #   list1.txtの内容を受け取ってしまう。)
    while read PRM2
    do
        # PRM2に何も入っていない場合
        if [ "$PRM2" = "" ]
        then
            # ループを抜ける
            break;
        fi

        # PRM2の内容を表示
        echo "\$PRM2=[$PRM2]"
    done
done < list1.txt

いろいろ調べるうち2通りの回避方法が見つかった。
・外側のループの入力を別のディスクリプタから受け取る。
・内側のループの入力を/dev/ttyから受け取る。

■外側のループの入力を別のディスクリプタから受け取る。
readコマンドのオプションに「-u ディスクリプタ番号」を付けるとその番号から入力を受けることができることを利用して行う。
例)

#!/bin/bash
# readコマンドで list1.txt の内容を1行 PRM1 に受け取る
while read -u 3 PRM1
do
    # PRM1の内容を表示
    echo "\$PRM1=[$PRM1]"

    # 標準入力をPRM2に受け取る。
    # (while read PRM1で ディスクリプタ3 を使っているため、
    #   問題ない)
    while read PRM2
    do
        # PRM2に何も入っていない場合
        if [ "$PRM2" = "" ]
        then
            # ループを抜ける
            break;
        fi

        # PRM2の内容を表示
        echo "\$PRM2=[$PRM2]"
    done
done 3<list1.txt

■内側のループの入力を/dev/ttyから受け取る。
内側のループを/dev/ttyから入力を受けるようにすると最初の標準入力と混じらずに入力を受けることができる。
例)

#!/bin/bash
# readコマンドで list1.txt の内容を1行 PRM1 に受け取る
while read PRM1
do
    # PRM1の内容を表示
    echo "\$PRM1=[$PRM1]"

    # 標準入力をPRM2に受け取る。
    while read PRM2
    do
        # PRM2に何も入っていない場合
        if [ "$PRM2" = "" ]
        then
            # ループを抜ける
            break;
        fi

        # PRM2の内容を表示
        echo "\$PRM2=[$PRM2]"
    done</dev/tty
done<list1.txt

参考元:Bash
Read input in bash inside a while loop

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*