web-dev-qa-db-ja.com

envでスペースを含む環境変数を設定する

私はenvを使用して、サブプロセスの環境変数(別のソース、たとえばファイルから読み取る)を設定しようとしています。基本的に、私は次のことを試みています:

env VALUE=thisisatest ./somescript.sh

たとえば、somescript.shは:

echo $VALUE

次に、これは期待どおりthisisatestを出力します。しかし、私はファイルから変数をロードしたいと思います。私はここまで来ました:

env $(cat .vars | xargs -d '\n') ./somescript.sh

しかし、変数にスペースが含まれていると問題が発生します(引用符が期待どおりに機能しない)。だから例えば:

env $(echo 'VALUE="this is a test"' | xargs -d '\n') ./somescript.sh

エラーになります

env: is: No such file or directory

そして試み:

env $(echo 'VALUE="thisisatest"' | xargs -d '\n') ./somescript.sh

予想外の結果をもたらすでしょう:

"thisisatest"

env VALUE="thisisatest" ./somescript.sh引用符なしで出力します。

エラーから、何らかの理由でenvが引用符が後続の値が文字列であることを意味することを理解していないことを理解します。ただし、引用符が正しく解釈されるようにこれらの変数を補間する方法がわかりません。

誰でも私がこれを達成する方法についてのヒントを提供できますか?

ありがとう!

6
Bailey Parker

コマンド置換では二重引用符が必要です。それ以外の場合、シェルはコマンド置換の結果を使用してフィールド分割を実行します。

$ env "$(echo 'VALUE="this is a test"')" ./somescript.sh
"this is a test"

ファイルからenvを読み取る場合は、シェルにフィールド分割を行わせる必要がありますが、IFSを改行のみに設定して、コマンドがスペースで中断しないようにします。

$ IFS='
'
$ env $(cat .vars) ./somescript.sh

ファイルから読み取りたい場合は、somescript.sh内のファイルをソース(別名 ドット )するだけの方が良いです。

#!/bin/bash

. .vars
: The rest of script go here
4
cuonglm

これは機能します:

_env -S "`cat .vars`" command
_

まず、ファイルで変数値を引用符で囲む必要があります。

_VALUE="This has spaces"
_

次に、_-S_フラグを使用して変数を解析します(引用符を取り除きます)。

_env -S "`cat .vars`" command-refers-to-env-vars
_

もちろん、コマンドで_$VALUE_を参照することはできません。これは、コマンドがenvのアクションに対してシェルpriorによって評価されるためです。そのためには、以下を使用する必要があります。

_( . .vars ; echo $VALUE )
_

括弧はサブシェルを開き、_.vars_のすべての定義でシェルを汚染しないようにします。ただし、変数はシェルでのみ使用できます。これらは実際にはenv内にないため、_process.ENV.VALUE_呼び出しの場合のように、プロセスは_env -S_またはgetenv("VALUE")を使用してそれらにアクセスできません。

両方を組み合わせることができます

_( . .vars ; env -S "`cat .vars`" command-refers-to-envs $VALUE )
_
3
frankleonrose

実際、これを行うにはもっと良い方法があり、問題なく複数の変数を宣言できます。

env {'VALUE=thisisatest','FOO=this is a test'} printenv
1
Vopel

複雑すぎると思います。

$ env FOO='this is a test' printenv | egrep -i foo
FOO=this is a test

ちなみに、引用符はthisの問題の一部ではありません。必要に応じて、二重引用符を使用します。たとえば、値に変数を代入します。変数の置換などを防ぎたい場合は、単一引用符を使用してください。

必要に応じて、コマンド置換を使用してください。書式化された文字列を使用します。両方を使う。

$ env FOO=$'this\tis a test' printenv | egrep -i foo | cat -t
FOO=this^Iis a test
$ env FOO="$(echo $'this\tis a test')" printenv | egrep -i foo | cat -t
FOO=this^Iis a test

おっと、これはコマンド置換を使用するより良い例かもしれません。アイデアは、不要なコマンド置換を単に不必要に使用するだけでなく、いくつかの必須コマンドの出力を変数に入れることです。

$ env FOO="$(man man)" printenv | egrep -iA5 foo=
FOO=man(1)                                    man(1)



NAME
   man - format and display the on-line manual pages
0
Larry