今日のおハマリは、とあるシェル関数の出力をevalするスクリプトです。
このシェル関数は、bashの配列を定義してそれをexportするものです。ですので、いつくかの配列がexportされるのが期待する結果です。
いまだに挙動がよくわかったようなわかってないようななんで、おしえてえらいひと!
比較のために、
- シェル関数: 行末にセミコロンをつけるかつけないか
- eval: するっとevalするか、evalする関数を呼ぶか
の組み合わせで 4 通り試します。
こんなスクリプトを:
call=$1 semicolon=$2 if [ "$semicolon" = "ari" ]; then evalme() { cat <<EOF HAHAHA_A=(Ei); export HAHAHA_A; HAHAHA_B=(Bi); export HAHAHA_B; HAHAHA_C=(Ci); export HAHAHA_C; EOF } elif [ "$semicolon" = "nasi" ]; then evalme() { cat <<EOF HAHAHA_A=(Ei); export HAHAHA_A HAHAHA_B=(Bi); export HAHAHA_B HAHAHA_C=(Ci); export HAHAHA_C EOF } else echo abort1 return 1 fi if [ "$call" = "direct" ]; then #set -x eval $(evalme) #set +x elif [ "$call" = "func" ]; then func_do_eval() { eval $(evalme); } #set -x func_do_eval #set +x else echo abort2 return 1 fi
引数を変えてsourceして、3つの配列 HAHAHA_A, B, Cが定義されるかみてみます:
$ unset HAHAHA_A HAHAHA_B HAHAHA_C; declare -x|grep HAHAHA; \ . sourceme.sh direct ari; declare -x|grep HAHAHA declare -ax HAHAHA_A='([0]="Ei")' declare -ax HAHAHA_B='([0]="Bi")' declare -ax HAHAHA_C='([0]="Ci")' $ unset HAHAHA_A HAHAHA_B HAHAHA_C; declare -x|grep HAHAHA; \ . sourceme.sh direct nasi; declare -x|grep HAHAHA declare -ax HAHAHA_A='([0]="Ei")' declare -ax HAHAHA_B='([0]="Bi")' declare -ax HAHAHA_C='([0]="Ci")' $ unset HAHAHA_A HAHAHA_B HAHAHA_C; declare -x|grep HAHAHA; \ . sourceme.sh func ari; declare -x|grep HAHAHA declare -ax HAHAHA_A='([0]="Ei")' declare -ax HAHAHA_B='([0]="Bi")' declare -ax HAHAHA_C='([0]="Ci")' $ unset HAHAHA_A HAHAHA_B HAHAHA_C; declare -x|grep HAHAHA; \ . sourceme.sh func nasi; declare -x|grep HAHAHA declare -ax HAHAHA_A='([0]="Ei")'
最初の3つは、A,B,Cの3つの配列がexportされているので期待した結果です。
んがっ!最後のはなんでかAしかexportされてません。
set -xすればexportされない理由はなんとなくわかるんですが。。。んじゃなんで2つめの直接evalったときはexportされるのでしょうか。。。
$ bash --version GNU bash, version 3.2.39(1)-release (x86_64-pc-linux-gnu) Copyright (C) 2007 Free Software Foundation, Inc.
ス。