编写Bash脚本替换/追加.env文件中的环境变量
用Awk实现.env文件的环境变量批量更新与追加
现有部署脚本参数中的环境变量字符串(格式如FOO=BAR,ABC=XYZ,ENV=PROD),需要对.env文件执行以下操作:
- 若变量键已存在,更新对应的值
- 若变量键不存在,追加到文件末尾
此前用sed实现的代码过于冗长,以下是更简洁高效的Awk方案。
完整实现脚本
#!/bin/bash # 1. 从部署脚本参数中提取环境变量字符串(示例值,实际可根据来源调整) DEPLOY_CMD="script=/deploy FOO=BAR,ABC=XYZ,ENV=PROD" DEPLOY_ENV=$(echo "$DEPLOY_CMD" | awk '{print $2}') # 2. 创建临时文件,避免直接修改原文件导致数据损坏 TMP_FILE=$(mktemp) # 3. 使用Awk批量处理.env文件 awk -v env_str="$DEPLOY_ENV" ' BEGIN { # 拆分逗号分隔的环境变量为键值对数组 pair_count = split(env_str, env_pairs, ",") for (i = 1; i <= pair_count; i++) { eq_pos = index(env_pairs[i], "=") if (eq_pos > 0) { key = substr(env_pairs[i], 1, eq_pos - 1) value = substr(env_pairs[i], eq_pos + 1) # 跳过空键或空值的无效项 if (key != "" && value != "") { new_env[key] = value processed[key] = 0 } } } } # 处理.env中的变量定义行 /^[A-Za-z_][A-Za-z0-9_]*=/ { key = substr($0, 1, index($0, "=") - 1) if (key in new_env) { # 存在则替换为新值 print key "=" new_env[key] processed[key] = 1 } else { # 不存在则保留原行 print $0 } next } # 保留注释、空行等非变量定义行 { print } # 追加.env中不存在的新变量 END { for (key in processed) { if (processed[key] == 0) { print key "=" new_env[key] } } } ' .env > "$TMP_FILE" # 4. 原子替换原.env文件 mv "$TMP_FILE" .env echo "环境变量更新完成"
脚本说明
核心逻辑
- 提取环境变量:从部署命令中拆分出逗号分隔的键值对字符串
- 临时文件处理:用
mktemp生成临时文件,确保文件修改的原子性,避免中途中断损坏原文件 - Awk批量处理:
BEGIN块:将部署脚本中的环境变量解析为键值对数组,标记待处理状态- 遍历.env文件:识别变量定义行,匹配到目标键则替换值,否则保留原内容;注释、空行等非变量行直接保留
END块:将未在.env中找到的变量追加到文件末尾
优势
- 单次扫描完成所有操作,比多次调用sed更高效
- 保留.env文件原有格式(注释、空行、变量顺序)
- 支持值中包含等号的特殊场景(如
FOO=BAR=BAZ) - 自动跳过无效的空键/空值项
注意事项
- 确保脚本有.env文件的读写权限
- 若部署脚本的环境变量来源不同(如从环境变量传入),只需调整
DEPLOY_ENV的赋值逻辑即可 - 可根据需求调整变量名的正则规则(当前规则为
^[A-Za-z_][A-Za-z0-9_]*=,符合POSIX变量命名规范)
内容的提问来源于stack exchange,提问作者Ajay k
相关产品推荐
相关产品推荐

