web-dev-qa-db-ja.com

変数名の接頭辞を変更して環境変数の名前を変更する

いくつかの環境変数があります。動的に変換したい値が複数あります。

環境変数:printenv | grep proj_env_repoを使用してこの環境変数を取得しています(printenv | grep $valueのように動作します)。

値はproj_env_repoです

そして私の結果は

proj_env_repo_db_username=username

TF_ENV_db_username=usernameに変換したい

誰かが私を助けてくれますか? bashスクリプトで関数を探しています。

4
Swat

bashでの変数名のプレフィックスの一致と変数の間接参照の使用:

proj_env_repo_db_username=username
proj_env_repo_db_Host=host
proj_env_repo_db_port=port

for variable in "${!proj_env_repo@}"; do
    export "TF_ENV${variable#proj_env_repo}"="${!variable}"
done

ループは"${!proj_env_repo@}"を使用して、名前のプレフィックスproj_env_repoを共有する変数名のリストを生成します。各反復で、$variableはこれらの変数の1つの名前になります。

ループ内では、exportを使用して、proj_env_repo接頭辞を取り除き、文字列TF_ENVで置き換えることにより、新しい環境変数を作成します。新しい環境変数の値は、変数の間接参照${!variable}、つまり、名前が$variableに格納されている変数の値を使用して取得されています。

元の変数をさらに設定解除するには、exportの後、ループの終了前にunset "$variable"を使用します。

トレースをオンにしてこれをテストして実行します。

$ bash -x script.sh
+ proj_env_repo_db_username=username
+ proj_env_repo_db_Host=host
+ proj_env_repo_db_port=port
+ for variable in "${!proj_env_repo@}"
+ export TF_ENV_db_Host=host
+ TF_ENV_db_Host=host
+ for variable in "${!proj_env_repo@}"
+ export TF_ENV_db_port=port
+ TF_ENV_db_port=port
+ for variable in "${!proj_env_repo@}"
+ export TF_ENV_db_username=username
+ TF_ENV_db_username=username

古い名前の接頭辞を1番目の引数として、新しい接頭辞を2番目の引数として取る関数として:

rename_var () {
    # Make sure arguments are valid as variable name prefixes
    if ! [[ $1 =~ ^[a-zA-Z_][a-zA-Z_0-9]*$ ]] ||
       ! [[ $2 =~ ^[a-zA-Z_][a-zA-Z_0-9]*$ ]]
    then
        echo 'bad variable name prefix' >&2
        return 1
    fi

    eval 'for variable in "${!'"$1"'@}"; do
              export "'"$2"'${variable#'"$1"'}"="${!variable}"
          done'
}

evalは構文${!$1@}をサポートしていないため、ここではループでbashを使用しています。関数は、$1および$2(関数に指定された1番目と2番目の引数)の値に従って変数の名前を変更するための適切なシェルコードを(文字列として)構築し、evalこのシェルコードを実行します。

この関数は次のように使用します

rename_var project_env_repo TF_ENV

...または、変数を使用して、

rename_var "$old_variable_prefix" "$new_variable_prefix"

注:(ユーザー入力でevalを使用して)このようなことを行う場合、評価するコードが有効であることをテストする必要がありますそれがあなたがそれであるとあなたが期待するものであるということ。この場合、これは、$1および$2を有効な変数名のプレフィックスとして検証することを意味します。そうでない場合、少なくとも引用符と}evalで構文エラーを引き起こし、コマンドインジェクションの可能性があります。


注:これは私がこれまでに使用したことが初めて(私が思う) eval を使用した 。ただし、上記のコードを使用する必要はありませんが、質問の背景知識がわからないため、質問に対する批判ではありません(それ自体が興味深い質問です)。

関連(ソフトウェアエンジニアリングサイト):

8
Kusalananda
while IFS='=' read -r name value; do
    new_name="TF_ENV${name#proj_env_repo}"
    export "$new_name=$value"
    unset "$name"
done < <( printenv | grep proj_env_repo )

ここの秘密の成分:

3
glenn jackman
for v in `printenv | grep proj_env_repo`
do
    eval `echo "$v=\$$v" | sed -e 's/proj_env_repo/TF_ENV/'`
    unset $v
done

echoは次のように出力します:

proj_env_repo_db_username=$proj_env_repo_db_username

sedは、proj_env_repoの最初のインスタンスをTF_ENVで変換します。

TF_ENV_db_username=$proj_env_repo_db_username

evalはそのステートメントを評価します。

unsetは、古い変数が削除されることを確認します。

1
Alexis Wilke