🐱

環境変数に使える文字のシェル毎の違い

2021/12/05に公開約3,300字

tl;dr

  • 環境変数に大文字、数値、アンダーバー以外は使わない方が無難だよ
  • ただし、それ以外の文字もシェルによっては使えることもあるよ

試してみる

いくつかのシェルで試してみます。最後のash以外はmacOS上での実行です。

# dashからだと見られない
bash-3.2$  env "hyphen-var=aaaaaaaaaaaaaab" /bin/dash -c 'env | grep hyphen'
# bashだと見られる
bash-3.2$  env "hyphen-var=aaaaaaaaaaaaaab" /bin/bash -c 'env | grep hyphen'
hyphen-var=aaaaaaaaaaaaaab
# zshからは見られない
env "hyphen-var=aaaaaaaaaaaaaab" /bin/zsh -c 'env | grep hyphen'
# fishからは見られる
env "hyphen-var=aaaaaaaaaaaaaab" /usr/local/bin/fish -c 'env | grep hyphen'
hyphen-var=aaaaaaaaaaaaaab
# sh(POSIX互換モードのbash?)からは見られる
bash-3.2$  env "hyphen-var=aaaaaaaaaaaaaab" /bin/sh -c 'env | grep hyphen'
hyphen-var=aaaaaaaaaaaaaab
# ashからは見られる
docker run -e "hyphen-var=aaaaaaaaaaaaaab" -it --rm alpine:3.15.0   /bin/ash -c 'env | grep hyphen'                                                         972ms  日 12/ 5 18:06:26 2021
hyphen-var=aaaaaaaaaaaaaab

# bash+declareからでも見られる
env "hyphen-var=aaaaaaaaaaaaaab" /bin/bash -c 'declare -x | grep hyphen'                                                                                                日 12/ 5 18:09:14 2021
declare -x hyphen-var="aaaaaaaaaaaaaab"

なんで違いがあるの

先人の知恵によると、

  • POSIX的には、環境変数は大文字、数値、アンダーバーで数値始まりでない名前はサポートしなければならない
    • Environment variable names used by the utilities in the Shell and Utilities volume of IEEE Std 1003.1-2001 consist solely of uppercase letters, digits, and the '_' (underscore) from the characters defined in Portable Character Set and do not begin with a digit.

  • ハイフンを含む環境変数名はサポートしなくても良い。ただし、実装が他の文字をサポートしてもよい
    • Other characters may be permitted by an implementation;

らしいです。

なんでわざわざ使えなくしているシェルがあるの

ハイフンわざわざ除外する方が実装の手間じゃない?と思いましたが、Stackexchangeの回答によると、セキュリティ(Shellshcokの影響)を気にしているらしいです。

Note that some shells (e.g. modern dash, mksh, zsh) remove variables whose name they don't like from the environment. (Shellshock has caused people to be more cautious about environment variable names, so restrictions are likely to become tighter over time, not more permissive.)

例えば、dashは古いバージョンはハイフン使えたのを2012年に使えなくしたようで、古いバージョン(2010年リリースのUbuntu lucid)のdashで試すと、確かにハイフン使えます。

# 古いバージョン(2010年リリース)のUbuntuのdashでは使える
docker run -e "hyphen-var=aaaaaaaaaaaaaab" -it --rm ubuntu:lucid   /bin/dash -c 'env | grep hyphen'                                           
hyphen-var=aaaaaaaaaaaaaab

# 新しいバージョン(2021年リリース)のUbuntuのdashでは使えない
docker run -e "hyphen-var=aaaaaaaaaaaaaab" -it --rm ubuntu:jammy   /bin/dash -c 'env | grep hyphen'

他の文字は

絵文字の環境変数名も(少なくともbashでは)使えました。

env "😺=aaaaaaaaaaaaaab" /bin/bash -c 'env | grep 😺'
😺=aaaaaaaaaaaaaab

ゼロ幅スペースも行けました(hereとzeroの間に存在)。

 env "here​zero=aaa" /bin/bash -c 'env | grep zero | od -a'                 
0000000    h   e   r   e   ?  80  8b   z   e   r   o   =   a   a   a  nl

Discussion

ログインするとコメントできます