通过更改变量名称前缀来重命名环境变量

通过更改变量名称前缀来重命名环境变量

我有一些环境变量。我想动态转换多个这样的值。

printenv | grep proj_env_repo环境变量:我使用(像这样)获取这个环境变量printenv | grep $value

所以值为proj_env_repo

我的结果是

proj_env_repo_db_username=username

我想将其转换为TF_ENV_db_username=username

有人可以帮我吗?我正在寻找 bash 脚本中的函数。

答案1

在中使用变量名前缀匹配和变量间接寻址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都会出现这些变量之一的名称。

在循环内部,export用于通过删除前缀proj_env_repo并将其替换为字符串来创建新的环境变量TF_ENV。新环境变量的值是使用变量间接寻址获得的${!variable},即名称存储在 中的变量的值$variable

要另外取消设置原始变量,请在循环结束之前使用unset "$variable"after , 。export

在打开跟踪的情况下测试运行它:

$ 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

作为一个函数,将旧名称前缀作为其第一个参数,将新前缀作为其第二个参数:

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'
}

由于不支持语法,我们在这里诉诸于使用evalover 循环。该函数构造适当的 shell 代码(作为字符串),用于根据和的值(赋予函数的第一个和第二个参数)重命名变量,然后用于执行此 shell 代码。bash${!$1@}$1$2eval

您可以将此函数用作

rename_var project_env_repo TF_ENV

...或者,使用变量,

rename_var "$old_variable_prefix" "$new_variable_prefix"

注意:当做这样的事情时(使用eval用户输入),你必须测试您评估的代码是否有效并且是否符合您的预期。在这种情况下,这意味着验证$1$2作为有效的变量名称前缀。否则至少引号 和}会导致 中出现语法错误eval,并且存在命令注入的可能性。


注意:这是我第一次(我认为)使用eval。我永远不会让自己处于必须使用上述代码的境地,但显然我不知道这个问题的背景故事,所以这并不是对这个问题的真正批评(这本身就是一个有趣的问题)。

相关(在软件工程网站上):

答案2

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 )

这里的秘密成分:

  • 外壳参数扩展
  • IFS='=' read -r name value-- 使用 = 符号将传入行拆分为组成部分。
  • 用一个流程替代所以 while 循环在当前 shell 中运行。

答案3

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

转换withsed的第一个实例。proj_env_repoTF_ENV

TF_ENV_db_username=$proj_env_repo_db_username

评估eval该陈述。

确保unset旧变量被删除。

相关内容