CUBE SUGAR CONTAINER

技術系のこと書きます。

シェル変数と環境変数

シェルで扱う変数にシェル変数と環境変数があることは何となく知っていた。 ただ、それぞれどう違うのかとか操作方法についてあまり意識したことがなかった。 なので一旦ここで整理しておくことにする。

今回使った環境は次の通り。

$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.4 LTS"
$ uname -r
3.16.0-30-generic

まず、今定義されているシェル変数は set コマンドを使って確認できる。

$ set
BASH=/bin/bash
BASHOPTS=checkwinsize:cmdhist:complete_fullquote:expand_aliases:extglob:extquote:force_fignore:histappend:interactive_comments:login_shell:progcomp:promptvars:sourcepath
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
BASH_CMDS=()
...(省略)

それに対して環境変数は env コマンドを使って確認する。

$ env
XDG_SESSION_ID=1
TERM=xterm-256color
SHELL=/bin/bash
SSH_CLIENT=10.0.2.2 50079 22
SSH_TTY=/dev/pts/0
USER=vagrant
...(省略)

シェル変数は <変数名>=<値> という形で宣言する。 試しに GREET という変数名を宣言してみよう。

$ GREET="Hello, World!"

これでシェル変数として GREET が見えるようになる。

$ set | grep GREET
GREET='Hello, World!'

変数の内容を参照するときは $<変数名> か ${<変数名>} という形でアクセスする。

$ echo $GREET
Hello, World!

もちろん、この状態では環境変数から GREET は見えない。

$ env | grep GREET
$

シェル変数は子プロセスに引き継がれないという特徴を持っている。 試しに Python の REPL を起動した上でシェル変数 GREET の内容にアクセスしてみよう。 シェルから起動した Python のプロセスは、シェルから見て子プロセスになる。

$ python
>>> import subprocess
>>> process = subprocess.Popen('echo $GREET', shell=True, stdout=subprocess.PIPE)
>>> stdout, _ = process.communicate()
>>> stdout
'\n'

このようにシェル変数は子プロセスに引き継がれないのでアクセスしても何も表示されない。

では次に環境変数を宣言してみよう。 これには export コマンドを使う。 export コマンドはシェル変数を環境変数にすることができる。

$ export GREET

環境変数になると env コマンドから見えるようになる。

$ env | grep GREET
GREET=Hello, World!

シェル変数とは違って環境変数は子プロセスに引き継がれる。 先ほどと同じように Python の REPL を起動して環境変数 GREET の内容にアクセスしてみよう。

$ python
>>> import subprocess
>>> process = subprocess.Popen('echo $GREET', shell=True, stdout=subprocess.PIPE)
>>> stdout, _ = process.communicate()
>>> stdout
'Hello, World!\n'

今度は環境変数なので内容が子プロセスに引き継がれた。

ちなみに環境変数であれば上記のようにシェルを介して確認する必要はない。 Python だとそれ用のインターフェースが os モジュールに用意されている。

$ python -c "import os; print(os.environ['GREET'])"
Hello, World!

シェル変数および環境変数を消去するには unset コマンドを使う。

$ unset GREET

これでシェル変数と環境変数の両方が一度に消去される。

$ env | grep GREET
$
$ set | grep GREET
$

ちなみに、環境変数を定義するには export コマンド以外にも declare コマンドに -x オプションを付けて実行する方法もある。

$ GREET="Hello, World!"
$ declare -x GREET

あと export コマンドであればシェル変数を介すことなく一発で環境変数を宣言することもできる。 普段はこれを使うはず。

$ export GREET="Hello, World!"

いじょう。