同じ範囲の配列の代わりに変数がsuコマンドに渡されるのはなぜですか?

同じ範囲の配列の代わりに変数がsuコマンドに渡されるのはなぜですか?

次の例では、開始関数の配列には$var渡されますが、su配列には渡されないのはなぜですかmodules

#!/bin/bash
var=cat
modules=(
one
two
three
four
)

start() {
    su gleventh -c "for i in ${modules[@]}; do echo -- $i -- $var;  done"
}

$1

echo "out of function"
for i in ${modules[@]}; do echo -- $i -- $var;  done

上記のスクリプトは以下を返します。

$ sudo ./test.sh start
-- -- cat
-- -- cat
-- -- cat
-- -- cat
out of function
-- one -- cat
-- two -- cat
-- three -- cat
-- four -- cat

答え1

問題は、suステートメントが二重引用符で囲まれているため、suコマンドが呼び出される前に変数が拡張されることです。つまり、 $var は "cat" になりますが $i は定義されていないため "" になります。 Bashはそれがイテレータ変数でなければならないことを知らず、ただNULL文字列に展開します。答えは、次のように「$」をエスケープすることです。

#!/bin/bash
var=cat
modules=(
one
two
three
four
)

start() {
    su gleventh -c "for i in ${modules[@]}; do echo -- \$i -- $var;  done"
}

$1

echo "out of function"
for i in ${modules[@]}; do echo -- $i -- $var;  done

答え2

${array[@]}配列に複数のメンバーがある場合、二重引用符で囲まれた特別なパラメータが単語分割を引き起こします。

$ for word in "for i in ${arr[@]} ; do" ; do echo "$word" ; done
for i in a
b
c ; do

モジュール名にスペースが含まれていない場合は、下付き*文字を使用することをお勧めします。

$ for word in "for i in ${arr[*]} ; do" ; do echo "$word" ; done
for i in a b c ; do

関連情報