能否让Bash的source命令不覆盖手动传入的环境变量?
问题说明
你当前使用的set -o allexport; source .env; set +o allexport加载逻辑会无条件覆盖所有已存在的同名环境变量,不符合「手动传入的变量优先级高于.env文件定义的变量」的需求。
解决方案
Ubuntu 20自带的Bash版本原生支持-v变量存在性判断语法,你可以用下面的代码加载.env文件,自动保留已手动传入的变量:
set -o allexport # 仅加载未在当前环境中定义的变量 while IFS= read -r line; do # 跳过注释行、空行 [[ $line =~ ^[[:space:]]*# || -z $line ]] && continue var_name="${line%%=*}" # 变量未定义才输出给source执行 [[ ! -v $var_name ]] && echo "$line" done < .env | source /dev/stdin set +o allexport
适配复杂.env格式的优化方案
如果你的.env文件存在值带引号、值包含等号的场景,可以用更严谨的写法:
# 逐行解析.env,跳过无效行,仅赋值未定义变量 while IFS='=' read -r key value; do # 跳过注释、空行 [[ $key =~ ^[[:space:]]*# || -z $key ]] && continue # 去除key前后的空格 key=$(echo "$key" | xargs) # 仅当变量未定义时赋值导出 if [[ ! -v $key ]]; then # 去除value首尾的引号和空格 value=$(echo "$value" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' -e 's/^"//' -e 's/"$//' -e "s/^'//" -e "s/'$//") export "$key=$value" fi done < .env
内容的提问来源于stack exchange,提问作者Leo Jiang
相关产品推荐
相关产品推荐

