Bashスクリプトがローカル環境変数の名前空間と競合しています。

Bashスクリプトがローカル環境変数の名前空間と競合しています。

bash scriptというファイルがありますVAR_A

私も地元env variableの名前があります。VAR_A

呼び出しbash scriptコマンド:

echo ${VAR_A}

スクリプトの変数を別の名前に変更することはできませんが、スクリプトがコマンドを呼び出す方法は変更できますecho

スクリプトに提供されているコマンドの代わりにechoローカルコマンドを印刷するようにコマンドを変更するにはどうすればよいですか?env variable

UPDATE FOR CLARITY:

状態:

ユーザーに.bashrcログイン時に設定された既存のファイルがあります。

VAR_A="someValue"
export VAR_A

これにより、ユーザーは次のことができます。

~]$ echo ${VAR_A}
    someValue

Bashスクリプト用のいくつかの設定ファイルがあります

VAR_A="someOtherValue"

Bashスクリプトがあります。

#!/bin/bash

. ../configuration  # imports config file with some values

#  do stuff

echo ${VAR_A}

端末(ログインしたユーザーとしてbashシェル)でスクリプトを実行すると、次のものが印刷されます。

~]$ ./run_script.sh
    someOtherStuff

印刷するには、次のものが必要です。

~]$ ./run_script.sh
    someStuff

答え1

シェル変数は各シェルの環境変数で初期化されるため、この問題を解決することはできません。

シェルが起動すると、有効な名前のシェル変数として受け取られる各環境変数に対して、シェルはそのシェル変数に適切な値を指定します。たとえば、スクリプトが次のように起動した場合:

env VAR_A=xxx your-script

(そしてshe-bangがあります#!/bin/bash -)がenv実行され、対応するbashコマンドに/bin/bash渡され、その変数に値が割り当てられます。VAR_A=xxxbash$VAR_Axxx

Bourne シェルと C シェルでシェル変数に新しい値を割り当てても、後でシェルで実行されるコマンドに渡される環境変数には影響しません。これを達成するには、exportまたはを使用する必要があります。setenvBourne シェルでは、unset変数を使用するとシェル変数と環境変数が削除されます。

存在する:

env VAR=xxx sh -c 'VAR=yyy; other-command'

sh現代のPOSIXシェルではなくBourneシェル)または:

env VAR=xxx csh -c 'set VAR = yyy; other-command'

other-commandVAR=xxxその環境でこれを受け取るには、代わりにVAR=yyy次のように書く必要があります。

env VAR=xxx sh -c 'VAR=yyy; export VAR; other-command'

または

env VAR=yyy csh -c 'setenv VAR yyy; other-command'

その環境で受信されますother-commandVAR=yyy

しかし、(POSIXと他のすべての現代のBourne様シェルが明らかになったkshように)、この問題が発生しました。bash

起動時に最新のシェル製本その環境変数にシェル変数を追加します。

これは、変数をエクスポートしなくても、スクリプトが変数の1つを設定するだけで環境を破壊する可能性があることを意味します。一部のシェルは、シェル変数にマップできない環境変数も削除します。したがって、シェルマッピング可能変数名のみを環境変数名として使用することをお勧めします。

これが慣例に従って、すべての大文字変数が環境変数用に予約されなければならない主な理由です。

この問題を解決するには、スクリプトによって実行されるコマンドがスクリプトを解釈するシェルと同じ環境を受け取るようにするには、何らかの方法でその環境を保存する必要があります。以下を追加するだけです。

my_saved_env=$(export -p)

スクリプトの先頭に次のコマンドを実行します。

(eval "$my_saved_env"; exec my-other-command and its args)

シェルboshmkshシェル、地元の関数の変数は環境変数を破壊しません(環境変数を破壊しない限り)。ただし、一部の特殊変数(たとえば、実行可能な照会のためのfor、...)をexport使用するシェル組み込み機能は、次のものを使用します。HOMEcdPATHシェル(ローカル)変数、環境変数ではありません。

$ env VAR=env mksh -c 'f() { local VAR=local; echo "$VAR"; printenv VAR; }; f'
local
env

答え2

VAR_A次の行を追加して変数を読み取り専用にすることができます。

readonly VAR_A

スクリプトの上部にあります。これにより、VAR_A次の値が発生します。予約する地域環境によって異なります。

readonly: readonly [-aAf] [name[=value] ...] or readonly -p

Mark shell variables as unchangeable.

Mark each NAME as read-only; the values of these NAMEs may not be
changed by subsequent assignment.  If VALUE is supplied, assign VALUE
before marking as read-only.

Options:
  -a        refer to indexed array variables
  -A        refer to associative array variables
  -f        refer to shell functions
  -p        display a list of all readonly variables and functions

An argument of `--' disables further option processing.

Exit Status:
Returns success unless an invalid option is given or NAME is invalid.

次の例を見ると明確になります。

$ export FOO="somevalue"        # environment variable FOO set to somevalue
$ cat test                      # test script
echo $FOO                       # print the value of FOO
readonly FOO                       # set FOO to local
FOO="something"                 # attempt to modify FOO
echo $FOO                       # print the value of FOO -- you would see the value that was inherited from the environment
$ bash test
somevalue
test: line 3: FOO: readonly variable
something

答え3

印刷したい場合地元のVariableはVAR_Aローカルスコープで呼び出す必要があります。それ以外の場合は、グローバル変数の値を印刷しますVAR_A

#! /bin/bash 

VAR_A="I'm global"

function lexical() {
    local VAR_A="I'm lexical"
    echo $VAR_A
}

echo -n "Global VAR_A: "
echo $VAR_A
echo -n "Lexical VAR_A: "
lexical

走る:

$ ./test.sh 
Global VAR_A: I'm global
Lexical VAR_A: I'm lexical

local次のページでbashの詳細を読むことができますman

local [option] [name[=value] ...]
              For each argument, a local variable named name is  created,  and
              assigned  value.   The option can be any of the options accepted
              by declare.  When local is used within a function, it causes the
              variable  name  to have a visible scope restricted to that func‐
              tion and its children.  With no operands, local writes a list of
              local  variables  to the standard output.  It is an error to use
              local when not within a function.  The return status is 0 unless
              local  is  used outside a function, an invalid name is supplied,
              or name is a readonly variable.

答え4

VAR_A何が起こっているのか設定ファイルVAR_A.bashrc

したがって、回避策自体は次のようになります。設定ファイルをインポートする前に、VAR_A次のように内容を保存してください。

VAR_A_sav=${VAR_A} # assuming that VAR_A_sav does NOT exist in configuration

. ../configuration # that is, you must choose a name not existing in config.

VAR_A=${VAR_A_sav}

関連情報