web-dev-qa-db-ja.com

ドット(。)を含む変数のエクスポート

ドットが含まれている変数をエクスポートする方法。私が試したときに「無効な変数名」が表示されます:

 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
41
user1587504

少なくともbashの場合、manページではエクスポート構文を次のように定義しています。

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が識別子の非常に類似した定義を持っているので、この種の変数も許可しないと確信しています。 (そのmanページを見てください。)

また、ある種の一般的な標準(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"}'

パスを印刷する必要があります。

54
michas

環境変数は等号またはnullバイトを含まない任意の名前(空の文字列を含む)を持つことができますが、シェルは環境変数をシェル変数にマップします。ほとんどのシェルでは、変数名はASCII英数字と_最初の文字を数字にすることはできません(位置パラメーターと、$*$-$@、…(これらは対応する環境変数にマップされていません)などの他の特殊なパラメーターを除く)。また、一部の変数は、シェルによって予約済み/特殊です。

その例外:

  • rcシェルとその派生物であるesakangaは、空の文字列を除くすべての名前と、すべて数値または=文字を含む名前をサポートします(そして常にすべての変数を環境にエクスポートし、*statusなどの特別な変数に注意してください。 __変数__...):

    ; '%$£"' = test
    ; echo $'%$£"'
    test
    ; '' = x
    zero-length variable name
    ;
    

    ただし、実行されているコマンドの環境に渡されたときに、名前にalnumが含まれていない変数または配列には独自のエンコーディングを使用します。

    $ 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 pidkshおよびyash(これもzshですが、シングルバイト文字のみ)は​​、ASCIIだけでなく、現在のロケールでalnumをサポートします。

    $ Stéphane=1
    $ echo "$Stéphane"
    1
    

    これらのシェルでは、ロケールを変更してほとんどの文字を英字と見なすことができますが、それでも.のようなASCII文字では機能しません。 bashまたはzshをだまして、£が文字であると考えることはできますが、.やその他のASCII文字は使用できません(変数名での文字の許可は、たとえば[[:alpha:]]グロブではありません)。

  • ksh93には、${.sh.version}のようなドットを含む名前の特殊変数がありますが、それらは環境変数にマップされておらず、特殊です。 .は、他の変数と競合しないことを確認するためのものです。それを$sh_versionと呼ぶことを選択した場合は、その変数をすでに使用しているスクリプトが壊れている可能性があります(たとえば、ksh$pathまたは$commandsの特殊な配列/ハッシュ変数(一部のスクリプトを壊す)に問題があることを確認してください)。

これらの変数をサポートしないシェルに加えて、pdksh/mkshなどの一部のシェルは、受け取る環境からそれらを実行removeします(zshは、空の名前、bashash、およびkshは、=文字を含まない環境文字列を削除します):

$ 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 %%%
%%%

要約すると、最善の方法は、ほとんどのシェルでサポートされている変数名を使い続け、環境変数に大文字(およびエクスポートされていないシェル変数に小文字または大文字と小文字)を使用して、シェルで特殊なもの(bashなど)を回避することです。 PS1BASH_VERSION...)。

それらをサポートしないがそれらを破棄しないシェルでそのような変数を設定する必要がある場合、次のようなもので自分自身を再実行することができます:

#! /bin/ksh -
Perl -e 'exit 1 unless defined($ENV{"a.b"})' || exec env a.b=%%% "$0" "$@"

(明らかに、スクリプトの途中でそれを行う必要がある場合、それは役に立ちませんが、re-overを介してシェル実行環境を保存および復元するために そのアプローチ を見ることができます-exec)。または、デバッガのアプローチを試してください:

gdb --batch-silent -ex 'call putenv("a.b=%%%")' --pid="$$"

(Linux AMD64でIFSzshyashcshtcshは動作するようですが、他のシェル(mkshksh93bashdash)では動作しません)。

9

他の投稿が指摘しているように、最も一般的なシェルでは、名前にピリオドを含む環境変数を設定できません。ただし、特にDockerと呼び出されたプログラムが関係し、ソフトウェアがピリオド付きのキー値を必要とする状況を発見しました。

ただし、これらの各状況で、これらのキーと値のペアは、環境変数だけでなく、他の方法でプログラムに渡すことができます。たとえば、Antでは、「-propertyfile(filename)」を使用して、プロパティファイル形式のKey-Valueのコレクションを渡すことができます。 Confdは「-backend file -file(yaml file)」を許可します。

「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

(正確な出力はシェルによって異なります。)引用エスケープをデコードするには、追加の手順を実行する必要があります。

2
Groboclown