bash(またはその他)で変数環境変数を設定する


9

スクリプトで、設定する環境変数のキーと値のペアを含むファイルを読み取ってから設定する必要があります。

これまでのところ、私はこれを持っています:

#!/bin/bash

cat $1 | while read kv
do
    key=${kv%=*}
    val=`echo ${kv#*=} | sed 's/^"\|"$//g'`
    export $key="$val"
done

そして、私はこのようなファイルを読みたいです:

XAUTHLOCALHOSTNAME="localhost"
DISPLAY=":0"
XAUTHORITY="/tmp/some-XAuthority"

スクリプトの実行中はスコープでこれらの変数のみが必要なので、親スコープのスクリプトで変数設定する問題を解決する必要はありません。

私のテストから、私の問題はexport $key="$val"にあると思うので、その行の交換が必要だと思います。


少し外れたトピックですが、スクリプトを模倣しようとしているときに動けなくなったので、共有しています...キーを取得するとき... %%と##が%と#と異なるため、削除された部分があるかどうかkey=${kv%%=*}よりもkey=${kv%=*}最短または最長の取り外し可能な部品です
pulkitsinghal 2013年

回答:


10

export $key=$valで問題なく動作するはずbashです。問題はパイプ(|)であると思われます。パイプライン内のすべてのコマンドはサブシェルで実行されます。あなたの例ではbash、スクリプトを実行しているそのインスタンスが2つのサブシェルを分岐します。1つはcat $1、もう1つはwhile read ...です。変数は、whileループを実行するサブシェルで割り当てられてエクスポートされ、サブシェルが終了すると、すべての変数が即座にスローされます。これを修正する1つの方法は、サブシェルをまったく生成しないことです。catを無用に使用する代わりに、代わりにリダイレクトを試してください:

while read ...; do
   ...
done < "$1"

BashFAQ 24はこれをより詳細に説明しています。

別の方法は、ファイルを調達するだけで、エクスポートがスローされます。

. <(sed '/^export/!s/^/export /' "$1")

<( )プロセス置換です。

注意の補足として、引数から環境変数を読み取っているので、引数ファイル$1が信頼できるソースであることを確認して、スクリプトに悪影響を及ぼすことがないようにする必要があります。


以前にリダイレクトを使用しました。スクリプトを使用するように変更したときに、他の何かが機能していないに違いありませんcat。しかし、リダイレクト付きのスクリプトが機能するようになりました。
パルスイム

有害とされる猫の無用な使い方!
スコット

2

jw013はすでに正しい答えを出していますが、さらにいくつかの問題を指摘したいと思います。)

パイプラインの右側は、bashの独自のサブシェルで実行されます(他のほとんどのシェルと同様、例外はATT kshとzshです)。つまり、ループを実行するサブシェルで環境変数を設定していますが、メインシェルプロセスでは設定していません。

ここにcat、リダイレクトによる無用な使用を置き換える簡単な修正があります:

while read …; do …; done <"$1"

一般に、入力を前処理する必要がある場合は、ループとスクリプトの残りの部分(少なくとも変更された変数を必要とする部分)をブロック内に配置します。

grep '^foo_' "$1" | {
  while read …; do …; done
  do_something
}

一般にwhile read line; do …、入力行を完全に反復しないことに注意してください。の代わりになぜがwhile IFS= read頻繁に使用されるのかをIFS=; while read..参照してください説明のために。入力行を反復する正しいイディオムは

while IFS= read -r line; do 

ここでは、サンプル入力が指定されていないため、先頭と末尾の空白の削除は重要ではありませんが、-rバックスラッシュの展開を避ける必要がある場合があります。それwhile read lineが実際に入力を読み取る正しい方法である可能性があります(ただし、変数値に改行が含まれていない場合にのみ疑います)。入力形式が曖昧であるか、解析が複雑である可能性もあります。変数の値の1つに改行文字、二重引用符、またはバックスラッシュが含まれている場合にどうなるかを確認します。

入力を確実に変換する1つのポイントは、値を抽出するときです。

val=`echo ${kv#*=} | sed 's/^"\|"$//g'`

まず、変数の置換を二重引用符で囲む必要がありecho "${kv#*=}"ます。それ以外の場合、シェルはワード分割とファイル名生成(つまり、グロビング)を実行します。2つ目echoは、aで始まる一部の文字列-はオプションとして扱われ、一部のシェルは引数に対してバックスラッシュ展開を実行するため、文字列を出力する信頼できる方法ではありません。文字列を印刷するための信頼できる移植可能な方法はprintf %s "${kv#*=}"です。また、値が複数行にわたる場合、sedプログラムはそれぞれ個別に動作しますが、これは誤りです。これは修正可能ですが、シェルの文字列操作機能を使用する簡単な方法がありますval=${kv#*=}; val=${val#\"}; val=${val%\"}

入力がplain readで正しく解析されると仮定すると、IFS各行を分割する設定を利用して、入力を解析する簡単な方法を次に示します。

while read name value; do
  value=${value#\"}; value=${value%\"}
  export name="$value"
done <"$1"


0

/ env

EXPORT=value
#NOTEXPORT=notvalue

脚本

#!/bin/sh

for entry in $(cat /env)
do
  if [[ ! $entry == \#* ]]
  then
    export $entry
  fi
done
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.