从环境文件中导出变量,值中包含空格

从环境文件中导出变量,值中包含空格

假设我有这个.env文件:

A=1
B=2
C="3 4 5"

如果我跑set -x; echo $(cat .env | xargs)

++ cat .env
++ xargs
+ echo A=1 B=2 C=3 4 5
A=1 B=2 C=3 4 5

如果我跑set -x; export $(cat .env | xargs)

++ cat /tmp/test.env
++ xargs
+ export A=1 B=2 C=3 4 5
+ A=1
+ B=2
+ C=3
bash: export: `4': not a valid identifier
bash: export: `5': not a valid identifier

然后我尝试了很多其他技巧来尝试保留或在C值周围添加引号:

$ set -x; export $(cat /tmp/test.env | xargs printf %q)
+ set -x
++ cat /tmp/test.env
++ xargs printf %q
+ export ''\''A=1'\'''\''B=2'\'''\''C=3' 4 '5'\'''
bash: export: `'A=1''B=2''C=3': not a valid identifier
bash: export: `4': not a valid identifier
bash: export: `5'': not a valid identifier

无论我做什么,C值总是按空格分割。

编辑:为了澄清,一个基于天真地采购 .env 文件的解决方案(大多数解决方案来自如何从文件中导出变量?)如果文件包含任何可以解释为命令执行的字符串,则非常不安全。我希望我的环境文件仅被解释为键值数据。

答案1

你能用吗parset

parset "`perl -nE '/[^=]+/ && print "$&,"' .env`" echo ::: "`perl -pe 's/[^=]+=//' .env`"

它可以愉快地处理如下输入:

vv=* ;   & " echo this is a value - not a command

答案2

xargs确实理解引用(尽管与 POSIX shell 的方式不完全相同),但运行xargs export不起作用,因为xargs只能运行独立的可执行文件,而不是 shell 的内置命令,例如export通常xargs不是内置命令。

不带引号的$(...)shell 构造本身执行 IFS 分割 + 通配符(不是 中的后者zsh),并且不处理引号(并且您不希望此处使用通配符部分)。

然而,由于您的 shell 是bash,您可以通过调用从文件中读取的记录来xargs输出 NUL 分隔的记录,并在 bash 中使用(需要 bash 4.4+ for )来拆分它,而不是 split+glob 运算符:printf '%s\0'readarray -td ''-d

readarray -td '' assignments < <(xargs -r < .env printf '%s\0')
(( ${#assignments[@]} == 0 )) || export -- "${assignments[@]}"

(这里使用 GNU 风格的-r选项来避免printf在输入没有记录时运行)。

相关内容