Bash while 文の中の変数が外で使えなくて困った話


解説用のコードなので、どんなときに使うんだというツッコミは無しの方向で。

奇数の ID が振られているアルファベットを表示したい

先に理由

while でぐるぐる回すときにはパイプを使っていろいろなものを読み込ませることが多い (個人的には) ですが、パイプを使うとその時点でサブシェルができてしまい、変数のスコープがサブシェルに行くからの模様。
なので、パイプを使わないようにして読み込ませると、ループの中で書き換えた変数が外で使えます。

動かないコード

while1.sh
#!/bin/bash -u
readonly settings=$(cat << EOS
1 A
2 B
3 C
4 D
5 E
6 F
7 G
8 H
EOS
)

target=""

echo "${settings}" | while read number alphabet
do
    if [ $(( number % 2 )) -eq 0 ]; then
       target=$( echo -e "${target}\n${alphabet}" )
    fi
done

echo "${target}"
$ bash ./while.sh

$

動くコード

while2.sh
#!/bin/bash -u
readonly settings=$(cat << EOS
1 A
2 B
3 C
4 D
5 E
6 F
7 G
8 H
EOS
)

target=""

while read number alphabet
do
    if [ $(( number % 2 )) -eq 0 ]; then
       target=$( echo -e "${target}\n${alphabet}" )
    fi
done << EOI
${settings}
EOI

echo "${target}"
$ bash ./while.sh
B
D
F
H
$