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

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

ポイントを含む変数をエクスポートする方法次の操作を試みると、「無効な変数名」というメッセージが表示されます。

 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英数字に制限されています_。最初の文字は、「tは数値です(位置パラメータ、および$*、、、$-...$@などの他の特殊パラメータを除外します(環境変数にマップされていません))。また、いくつかの変数は次のとおりです。予約/特別シェルを通して/シェルに。

例外:

  • シェルrcとその派生は、空の文字列を除くすべての名前はもちろん、数字または文字を含む名前をサポートしますes(常にすべての変数を環境にエクスポートし、、、...などの特殊変数を処理します)。akanga=*statuspid

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

    ただし、実行コマンドのコンテキストで渡されると、名前に数字が含まれていない変数または配列には独自のエンコーディングが使用されます。

    $ 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&Tkshおよび(yashシングルバイト文字のみ)ASCII文字だけでなく、現在のロケールの数もサポートします。zshbash

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

    これらのシェルでは、ほとんどの文字をアルファとして扱うようにロケールを変更できますが、ASCII文字(たとえば)の場合はそうではありません。文字とだまされたり考えたりすることができますが、その文字や他の.ASCII文字(変数名から)はそうではありません。 globなどの文字はで許可されています。zshksh£.[[:alpha:]]

  • ksh93名前にドットを含む特殊変数(例:)がありますが、${.sh.version}これらの変数は環境変数にマップされず、特殊です。これは.他の変数と競合しないようにするためです。呼び出すことを選択すると、すでにその変数を使用しているスクリプトが中断される可能性があります$sh_version(たとえば、その変数または特殊な配列zsh/$pathハッシュ$commands変数(a la csh)が一部のスクリプトを中断する問題がある方法を参照してください)。

これらの変数をサポートしていないシェルに加えて、いくつかのシェル(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 %%%
%%%

ほとんどのシェルでサポートされている変数名に固執するのが最善です。環境変数には大文字を使用し(エクスポートされていないシェル変数には小文字または大文字と小文字の混合)、シェル固有の変数名(たとえば、、、など)を使用しないことをお勧めIFSPS1ます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)では動作しません。)cshtcshmkshksh93bashdash

答え3

他の記事で指摘したように、ほとんどの一般的なシェルは名前にピリオドを含む環境変数の設定を許可しません。しかし、特にDockerおよび呼び出しプログラムに関して、ソフトウェアにピリオドを含むキー値が必要な場合があることがわかりました。

ただし、各場合、これらのキーと値のペアは、環境変数以外の手段を介してプログラムに渡すことができます。たとえば、Antでは、「-propertyfile(filename)」を使用して、属性ファイル形式でキー値セットを渡すことができます。 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

@michasの答えは非常に正確ですが、ドットexport環境名を使用して関数をシミュレートするように拡張できます。

execこれらの変数を「エクスポートするには」現在のシェルでコマンドを使用できますenv。たとえば、test.env=foo変数をエクスポートするには、次のようにします。

exec env "test.env=foo" $SHELL

Execは現在のシェルを新しいプロセスに置き換えます。ここで、新しいプロセスは、追加の$SHELL環境変数test.env(で追加env "test.env=foo")を持つ現在のシェル()の新しいインスタンスになります。したがって、このコマンドを実行した後、次のプロセスからアクセスできます。

perl -e 'print $ENV{"test.env"}'

関連情報