Zsh导出忽略引号和反斜杠

时间:2021-05-29 23:12:53

标签: shell environment-variables zsh

我有一个 shell 脚本(我们称之为 produce.sh),它以以下形式输出数据,但不将其保存到文件中:

FOO=value
BAR=value2
ZAP=value3

我想在 shell 脚本中使用这些值作为环境变量。我目前正在使用以下 shell 代码执行此操作:

export $(./produce.sh)

这很好用,除非 = 右侧的值包含空格。例如:

FOO=split value

我在 produce.sh 中尝试了两种不同的方法:

  1. 将值括在引号 (FOO="split value") 中
  2. 使用反斜杠 (FOO=split\ value) 转义空格

这两个都不起作用:如果我检查环境变量,FOO 在第一个示例中包含 "split,在第二个示例中包含 split\

我怎样才能让 export 正确处理这个问题?

2 个答案:

答案 0 :(得分:5)

f 中的 zsh 参数扩展标志将在换行符上拆分输入,因此这应该处理带有空格的输入值:

export ${(f)"$(./produce.sh)"}

发生了什么

produce.sh 的输出:

  • 键值对。
  • 每个 kv 对都在自己的行上。
  • 键与值之间用 = 分隔。
  • 语法类似于 shell,但不完全是 shell 语法,因此,
  • 值中允许使用空格和其他一些 shell 特有的字符。

替换部分:

  • produce.sh :生成键值输出,例如:N=V1\nP=V 2\n
  • $(...) :命令替换。它被替换为输出,减去尾随换行符:N=V1\nP=V 2
  • "..." :引号确保将先前的结果视为下一步的单个术语。
  • ${(f)...} :将该单个术语扩展为多个标量值,由于 (f) 标志而在换行符处拆分。结果实际上是 'N=V1' 'P=V 2'
  • export :分配和导出每个参数,作用类似于 export 'N=V1' 'P=V 2'

另一种选择

下面的替换添加了一些其他神秘的 zsh-isms 来创建关联数组。这避免了将任意变量添加到消费 shell 的 环境:

% ./s2.sh
A=A
B=
C=C C
% typeset -A vals=("${(@s:=:)${(f)"$(./s2.sh)"}}")
% print ${vals[A]}
A
% print ${vals[C]}
C C

一个小的折衷——如果值包含一个等号,这将不起作用,例如 D=D=D

答案 1 :(得分:0)

FOO=split value

是否将变量设置为包含空格的值。它临时将 FOO 设置为 split 并在已设置 value 的环境中运行命令 FOO。整体效果类似

(export FOO=split; value)

您可以通过执行此操作进行实验

FOO=split printenv

将运行 printenv 并在其输出中显示 FOO 的值。

要将变量设置为包含空格的值,您需要对空格进行转义,例如使用

FOO=split\ value

或使用引号。

为了处理这个文件,你可以使用 eval:

eval export $(./produce.sh)

当然,只有在您完全控制了 producer.sh 写入标准输出的内容时才应该这样做(即不要让任何受污染的数据潜入),因为 eval 是一个潜在的安全漏洞。

或者,您可以修改produce.sh 以在每行前面生成export 前缀,然后只做一个

eval $(./produce.sh)
相关问题