ドットを含む変数をエクスポートする方法。試してみたところ、「無効な変数名」というエラーが表示されます:
export my.home=/tmp/someDir
-ksh: my.home=/tmp/someDir: invalid variable name
メタ文字ドット(.)をエスケープしても効果はありませんでした
$ export my\.home=/tmp/someDir
export: my.home=/tmp/someDir: is not an identifier
答え1
少なくともbash
マニュアル ページでは、エクスポート構文は次のように定義されています。
export [-fn] [name[=word]] ...
また、「名前」は次のように定義されます。
name A word consisting only of alphanumeric characters and under‐
scores, and beginning with an alphabetic character or an under‐
score. Also referred to as an identifier.
my.home
したがって、有効な識別子ではないため、のような変数を実際に定義することはできません。
お使いの ksh にも、識別子の定義が非常によく似ており、したがってこの種の変数も許可されていないことは間違いありません。(マニュアル ページを参照してください。)
また、識別子 (つまり変数名) として何が許可されるかを指定する、ある種の一般的な標準 (POSIX?) が存在することも確信しています。
何らかの理由でこの種の変数が本当に必要な場合は、次のようなものを使用できます。
env "my.home=/tmp/someDir" bash
とにかく定義します。しかし、通常のシェル構文を使用してアクセスすることはできません。この場合、おそらく perl などの別の言語が必要になります。
perl -e 'print $ENV{"my.home"}'
例えば
env "my.home=/tmp/someDir" perl -le 'print $ENV{"my.home"}'
パスが印刷されるはずです。
答え2
環境変数は等号やヌルバイトを含まない任意の名前(空文字列を含む)を持つことができますが、シェルは環境変数をシェル変数にマッピングします。ほとんどのシェルでは、変数名はASCII英数字に制限され、_
最初の文字は数字にできません(位置パラメータと$*
、、、、 …$-
などのその他の特殊パラメータ$@
(対応する環境変数にマッピングされません)を除く)。また、一部の変数は予約済み/特別シェルによって/シェルに。
例外:
シェル
rc
と、 や などのその派生はes
、akanga
空の文字列を除く任意の名前、すべて数値または文字を含む名前をサポートします(また、常にすべての変数を環境にエクスポートし、 、、 ...=
などの特殊変数に注意してください)。*
status
pid
; '%$£"' = test ; echo $'%$£"' test ; '' = x zero-length variable name ;
ただし、名前に alnums が含まれない変数や、実行されるコマンドの環境で渡される配列には、独自のエンコーディングが使用されます。
$ rc -c '+ = zzz; __ = zzz; a = (zzz xxx); env' | sed -n /zzz/l __2b=zzz$ __5f_=zzz$ a=zzz\001xxx$ $ env +=x rc -c "echo $'+'" x $ env __2b=x rc -c "echo $'+'" x
AT&Tおよび(シングルバイト文字のみ) は
ksh
、 ASCII だけでなく、現在のロケールの alnums もサポートします。yash
zsh
bash
$ Stéphane=1 $ echo "$Stéphane" 1
これらのシェルでは、ほとんどの文字をアルファベットと見なすようにロケールを変更できますが、それでも などの ASCII 文字には機能しません。 または を文字であると思わせることは
.
できますが、や他の ASCII 文字 (変数名に文字を許可するかどうかは関係ありませんが、たとえば glob の場合はそうではありません) を思い込ませることはできません。zsh
ksh
£
.
[[:alpha:]]
ksh93
には、のように名前にドットが含まれる特別な変数があります${.sh.version}
が、これらは環境変数にマップされず、特別です。 は、.
他の変数と競合しないようにするためのものです。 を呼び出すことを選択した場合$sh_version
、その変数を既に使用しているスクリプトが壊れる可能性があります (たとえば、には のまたは一部のスクリプトを壊す特別な配列/ハッシュ変数 (csh など)zsh
に関する問題があります)。$path
$commands
これらの変数をサポートしていないシェルに加えて、pdksh/mkshなどの一部のシェルでは、取り除く受け取った環境からそれらを削除します (空bash
の名前を持つもの、 を削除しash
、文字を含まない環境文字列を削除します)。ksh
bash
=
$ env %%%=test 1=%%% a.b=%%% mksh -c env | grep %%%
$ env %%%=test 1=%%% a.b=%%% bash -c env | grep %%%
%%%=test
a.b=%%%
1=%%%
$ perl -le '$ENV{""}="%%%"; exec "bash", "-c", "env"' | grep %%%
$ perl -le '$ENV{""}="%%%"; exec "zsh", "-c", "env"' | grep %%%
=%%%
$ echo 'main(){char*a[]={"sh","-c","env",0};char*e[]={"%%%",0};
execve("/bin/ash",a,e);}'|tcc -run - | grep %%%
$ echo 'main(){char*a[]={"sh","-c","env",0};char*e[]={"%%%",0};
execve("/bin/zsh",a,e);}'|tcc -run - | grep %%%
%%%
まとめると、ほとんどのシェルでサポートされている変数名を使用し、環境変数には大文字を使用し (エクスポートされていないシェル変数には小文字または大文字と小文字の混在を使用)、シェルで特殊な変数 ( IFS
、、PS1
などBASH_VERSION
) を避けるのが最善です。
そのような変数をサポートしていないが破棄はしないシェルでそのような変数を設定する必要があるときは、次のようにして自分で再実行することができます。
#! /bin/ksh -
perl -e 'exit 1 unless defined($ENV{"a.b"})' || exec env a.b=%%% "$0" "$@"
(もちろん、スクリプトの途中でこれを行う必要がある場合は役に立ちませんが、その場合はそのアプローチシェルの実行環境を保存して再実行で復元します。または、デバッガーのアプローチを試してください。
gdb --batch-silent -ex 'call putenv("a.b=%%%")' --pid="$$"
(これはLinux amd64 上のzsh
、yash
、csh
では動作するようですtcsh
が、私が試した他のシェル ( mksh
、ksh93
、 ) では動作bash
しませんdash
)。
答え3
他の投稿で指摘されているように、最も一般的なシェルでは、名前にピリオドを含む環境変数を設定することはできません。ただし、特に Docker と呼び出されたプログラムが関係する状況では、ソフトウェアがピリオドを含むキー値を必要とする状況が見つかりました。
ただし、これらの状況のいずれにおいても、これらのキーと値のペアは、環境変数以外の手段でプログラムに渡すことができます。たとえば、Ant では、「-propertyfile (ファイル名)」を使用して、プロパティ ファイル形式のキーと値のコレクションを渡すことができます。Confd では、「-backend file -file (yaml ファイル)」を使用できます。
環境変数を「C__any_value='my.property.key=the value'」の形式で渡しました。次に、プログラムの呼び出しを切り替えて、最初にファイルを生成します。
set | awk -- 'BEGIN { FS="'\''" } /^C__/ {print $2}' > my-key-values.txt
Borne Shellのコマンドset
は、各プロパティを次の形式で別々の行に出力します。
C__any_value='my.property.key=the value'
このawk
コマンドは、 で始まる環境変数のみを処理しC__
、一重引用符で囲まれた値を抽出します。
この方法では、環境変数の値を処理プログラムが要求する正確な形式で設定する必要があります。さらに、プロパティ値またはキーに一重引用符が含まれる場合は、awk フィールド区切り文字を、表示されないことがわかっている文字に変更し、その文字で値を囲む必要があります。たとえば、%
区切り文字として使用するには、次のようにします。
$ C__1="%my.key=the'value%"
$ set | awk -- 'BEGIN { FS="%" } /^C__/ {print $2}'
my.key=the'"'"'value
(正確な出力はシェルによって異なります。) 引用符のエスケープをデコードするには、追加の手順を実行する必要があります。
答え4
export
@michas からの回答はまったく正しいですが、ドット環境名を使用して関数をシミュレートするように拡張することは可能です。
このような変数を「エクスポート」するには、コマンドexec
を使用して現在のシェルを実行しますenv
。たとえば、test.env=foo
変数をエクスポートするには、次を使用します。
exec env "test.env=foo" $SHELL
$SHELL
Exec は現在のシェルを新しいプロセスに置き換えます。新しいプロセスは、追加の環境変数test.env
( によって追加)を持つ現在のシェル ( ) の新しいインスタンスになりますenv "test.env=foo"
。したがって、このコマンドを実行すると、プロセスからアクセスできます。例:
perl -e 'print $ENV{"test.env"}'