子プロセスで親プロセスの環境変数を変更したい
...が,簡単にはできないらしい.今やりたいことを整理すると: (1) ある bash スクリプト hoge.sh では何か環境変数が定義される,(2) シェル (tcsh) で hoge.sh を実行して,hoge.sh の中で定義される環境変数をシェルで使いたい,(3) hoge.sh は変更しない.
使ってるシェルが bash なら,以下で解決.
. hoge.sh
tcsh だから話がややこしくなってる.子プロセス (hoge.sh) で定義された環境変数を無理やり tcsh で使う方法を考えた.
アイディア
- bash を(子プロセスとして)実行し,printenv; . hoge.sh; printenv の順に実行.
- 各 printenv の出力を保存しておき,差分を取って,変更があった環境変数を,親プロセス(tcsh スクリプト)上で再度定義する.
で,この tcsh スクリプトを source で実行すると,hoge.sh で変更される環境変数が,シェル上でも使えるようになる.
実装
set bashscript=$1 set tmp=/tmp/tmp$$ \bash -c "\ printenv > $tmp-a; \ . $bashscript; \ printenv > $tmp-b" set newv=`\diff \ --old-group-format='' \ --unchanged-group-format='' \ $tmp-a $tmp-b` \rm $tmp-a \rm $tmp-b foreach n1 ($newv) set n2=`echo $n1 | sed 's/\([a-zA-Z_]\+\)=\(.*\)/\1 \"\2\"/g'` eval "setenv $n2" end
- 余談だが,diff にこんなオプションがあるのは知らなかった.
- printenv の出力結果は A=B みたいな感じだから,A "B" のように sed で置換する.
- (環境)変数名が変数に含まれているから,eval を使う.
このスクリプトを,以下のように使う:
source copy_bash_env.tcsh hoge.sh
これで,hoge.sh で変更された環境変数が,このスクリプトを実行したシェル (tcsh) にも反映される.
もっと簡単な方法は...?