Zsh 导出忽略引号和反斜杠
Zsh export ignoring quotes and backslashes
我有一个 shell 脚本(我们称之为 produce.sh
),它以下列形式输出数据,但不将其保存到文件中:
FOO=value
BAR=value2
ZAP=value3
我想在 shell 脚本中将这些值用作环境变量。我目前正在使用以下 shell 代码执行此操作:
export $(./produce.sh)
这很好用,除非 =
右边的值包含空格。例如:
FOO=split value
我在 produce.sh
中尝试了两种不同的方法:
- 将值用引号引起来 (
FOO="split value"
)
- 使用反斜杠转义空格 (
FOO=split\ value
)
这两个都不起作用:如果我检查环境变量,FOO
在第一个示例中包含 "split
,在第二个示例中包含 split\
。
我怎样才能 export
正确处理这个问题?
zsh
中的 f
参数扩展标志将在换行符上拆分输入,因此这应该处理带有 whitespace:
的输入值
export ${(f)"$(./produce.sh)"}
发生了什么事
produce.sh的输出:
- 键值对。
- 每个 kv 对在其自己的行上。
- key 和 value 被
=
隔开。
- 语法类似于 shell,但不完全是 shell 语法,因此,
- white space 和一些其他 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
.
FOO=split value
是否未将变量设置为包含space的值。它临时将 FOO
设置为 split 并且 运行 在已设置 FOO
的环境中执行命令 value
。整体效果类似
(export FOO=split; value)
您可以通过
来试验一下
FOO=split printenv
这将 运行 printenv
并在其输出中显示 FOO
.
的值
要将变量设置为包含 space 的值,您需要转义 space,例如
FOO=split\ value
或使用引号。
要处理此文件,您可以使用 eval
:
eval export $(./produce.sh)
当然,只有当您完全控制 produce.sh 正在写入标准输出的内容时才应该这样做(即不要让任何受污染的数据潜入),因为 eval
是一种潜在的安全措施孔.
或者,您可以修改 produce.sh 以在每行前面生成 export
前缀,然后只执行
eval $(./produce.sh)
我有一个 shell 脚本(我们称之为 produce.sh
),它以下列形式输出数据,但不将其保存到文件中:
FOO=value
BAR=value2
ZAP=value3
我想在 shell 脚本中将这些值用作环境变量。我目前正在使用以下 shell 代码执行此操作:
export $(./produce.sh)
这很好用,除非 =
右边的值包含空格。例如:
FOO=split value
我在 produce.sh
中尝试了两种不同的方法:
- 将值用引号引起来 (
FOO="split value"
) - 使用反斜杠转义空格 (
FOO=split\ value
)
这两个都不起作用:如果我检查环境变量,FOO
在第一个示例中包含 "split
,在第二个示例中包含 split\
。
我怎样才能 export
正确处理这个问题?
zsh
中的 f
参数扩展标志将在换行符上拆分输入,因此这应该处理带有 whitespace:
export ${(f)"$(./produce.sh)"}
发生了什么事
produce.sh的输出:
- 键值对。
- 每个 kv 对在其自己的行上。
- key 和 value 被
=
隔开。 - 语法类似于 shell,但不完全是 shell 语法,因此,
- white space 和一些其他 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
.
FOO=split value
是否未将变量设置为包含space的值。它临时将 FOO
设置为 split 并且 运行 在已设置 FOO
的环境中执行命令 value
。整体效果类似
(export FOO=split; value)
您可以通过
来试验一下FOO=split printenv
这将 运行 printenv
并在其输出中显示 FOO
.
要将变量设置为包含 space 的值,您需要转义 space,例如
FOO=split\ value
或使用引号。
要处理此文件,您可以使用 eval
:
eval export $(./produce.sh)
当然,只有当您完全控制 produce.sh 正在写入标准输出的内容时才应该这样做(即不要让任何受污染的数据潜入),因为 eval
是一种潜在的安全措施孔.
或者,您可以修改 produce.sh 以在每行前面生成 export
前缀,然后只执行
eval $(./produce.sh)