TL;DR:如何从文本文件中导出一组键/值对到shell环境中?
为了记录在案,以下是问题的原始版本,并附有示例。
我在bash中写了一个脚本,它在某个文件夹中解析带有3个变量的文件,这是其中之一:
MINIENTREGA_FECHALIMITE="2011-03-31"
MINIENTREGA_FICHEROS="informe.txt programa.c"
MINIENTREGA_DESTINO="./destino/entrega-prac1"
该文件的存放路径为。/conf/prac1
我的脚本minientrega.sh然后使用以下代码解析文件:
cat ./conf/$1 | while read line; do
export $line
done
但是当我在命令行中执行minientrega.sh prac1时,它不会设置环境变量
我也尝试使用source ./conf/$1,但同样的问题仍然适用
也许还有其他方法可以做到这一点,我只需要使用我传递的文件的环境变量作为脚本的参数。
我用这个:
source <(cat .env \
| sed -E '/^\s*#.*/d' \
| tr '\n' '\000' \
| sed -z -E 's/^([^=]+)=(.*)/\1\x0\2/g' \
| xargs -0 -n2 bash -c 'printf "export %s=%q;\n" "${@}"' /dev/null)
首先删除评论:
sed -E '/^\s*#.*/d'
然后转换为空分隔符而不是换行符:
tr '\n' '\000'
然后用null替换equal:
sed -z -E 's/^([^=]+)=(.*)/\1\x0\2/g'
然后打印对到有效的带引号的bash导出(使用bash printf for %q):
xargs -0 -n2 bash -c 'printf "export %s=%q;\n" "${@}"' /dev/null
最后是来源。
它应该适用于所有特殊字符的所有情况。
这可能会有帮助:
export $(cat .env | xargs) && rails c
我使用这个的原因是如果我想在我的rails控制台中测试。env的东西。
Gabrielf想出了一个保持变量局部的好方法。这解决了从一个项目到另一个项目时的潜在问题。
env $(cat .env | xargs) rails
我已经用bash 3.2.51(1)-release测试了这一点
更新:
要忽略以#开头的行,使用这个(感谢Pete的评论):
export $(grep -v '^#' .env | xargs)
如果你想取消文件中定义的所有变量,使用这个:
unset $(grep -v '^#' .env | sed -E 's/(.*)=.*/\1/' | xargs)
更新:
要处理带有空格的值,请使用:
export $(grep -v '^#' .env | xargs -d '\n')
在GNU系统上——或者:
export $(grep -v '^#' .env | xargs -0)
在BSD系统上。
从这个答案中,你可以自动检测操作系统:
export-env.sh
#!/bin/sh
## Usage:
## . ./export-env.sh ; $COMMAND
## . ./export-env.sh ; echo ${MINIENTREGA_FECHALIMITE}
unamestr=$(uname)
if [ "$unamestr" = 'Linux' ]; then
export $(grep -v '^#' .env | xargs -d '\n')
elif [ "$unamestr" = 'FreeBSD' ] || [ "$unamestr" = 'Darwin' ]; then
export $(grep -v '^#' .env | xargs -0)
fi
使用shdotenv
dotenv支持shell和posix兼容的.env语法规范
https://github.com/ko1nksm/shdotenv
eval "$(shdotenv)"
使用
Usage: shdotenv [OPTION]... [--] [COMMAND [ARG]...]
-d, --dialect DIALECT Specify the .env dialect [default: posix]
(posix, ruby, node, python, php, go, rust, docker)
-s, --shell SHELL Output in the specified shell format [default: posix]
(posix, fish)
-e, --env ENV_PATH Location of the .env file [default: .env]
Multiple -e options are allowed
-o, --overload Overload predefined environment variables
-n, --noexport Do not export keys without export prefix
-g, --grep PATTERN Output only those that match the regexp pattern
-k, --keyonly Output only variable names
-q, --quiet Suppress all output
-v, --version Show the version and exit
-h, --help Show this message and exit
需求
Shdotenv是一个内置awk脚本的单文件shell脚本。
POSIX shell (dash, bash, ksh, zsh, etc)
awk (gawk, nawk, mawk, busybox awk)
source的问题在于它要求文件具有正确的bash语法,而一些特殊字符会破坏它:=、"、'、<、>等。所以在某些情况下你可以
source development.env
它会起作用的。
然而,这个版本可以承受值中的所有特殊字符:
set -a
source <(cat development.env | \
sed -e '/^#/d;/^\s*$/d' -e "s/'/'\\\''/g" -e "s/=\(.*\)/='\1'/g")
set +a
解释:
-a意味着每个bash变量都将成为环境变量
/^#/d删除注释(以#开头的字符串)
/^\s*$/d删除空字符串,包括空格
"s/'/'\\\ " /g"将每个单引号替换为'\ ",这是bash中的一个生成引号的技巧序列:)
"s/=\(.*\)/='\1'/g"将每个a=b转换为a='b'
因此,你可以使用特殊字符:)
要调试这段代码,将source替换为cat,您将看到该命令产生的结果。