【发布时间】:2017-05-18 13:55:51
【问题描述】:
Bash 4.4 和 4.3 似乎在将变量传递到子 shell 或 heredocs 方面表现不同。
来自@CharlesDuffy 的简单复制:
export var=0; var=1 cat <<<"$(env | grep '^var')"
Bash 4.4 输出var=0,bash 4.3 输出var=1。
我用于重现问题的原始脚本:
TZ=Europe/London
timezone=Asia/Tokyo
echo TZ=$TZ
echo timezone=$timezone
date +%H:%M
TZ=$timezone date +%H:%M
IFS=':' TZ=$timezone read hour minute <<EOF
$(date +%H:%M)
EOF
echo TZOUTER $hour-$minute
IFS=':' read hour minute <<EOF
$(TZ=$timezone date +%H:%M)
EOF
echo TZINNER $hour-$minute
Bash 4.3 (Ubuntu 16.04) 提供:
TZ=Europe/London
timezone=Asia/Tokyo
14:52
22:52
TZOUTER 22-52
TZINNER 22-52
Bash 4.4 (Ubuntu 17.04) 提供:
TZ=Europe/London
timezone=Asia/Tokyo
13:53
22:53
TZOUTER 13-53
TZINNER 22-53
(在 bash 4.3 上,内部和外部方法给出相同的时间,在 bash 4.4 上,TZOUTER 给出原始 TZ 值)。
有人知道为什么会这样吗?我查看了https://lists.gnu.org/archive/html/info-gnu/2016-09/msg00008.html,但无法确定是哪个更改导致了行为改变。
【问题讨论】:
-
明确地说,bash 4.4 的行为让我觉得更正确。
TZ=$timezone read ...应该只影响read命令的实际执行。它不会影响命令参数的扩展,那么为什么期望它会影响 heredoc 是合理的呢? -
顺便说一句,您是否考虑构建一个更简单的复制器?这需要相当多的解释。我建议将
var=0; var=1 cat <<<"$var"作为一个简明扼要地展示行为差异的单行符。 -
参见,例如,stackoverflow.com/questions/33476446/…。
bash有几个关于环境修饰符的错误,这里的文档/字符串已在过去几个版本中得到修复。 -
相比之下,
export var=0; var=1 cat <<<"$(env | grep '^var')"确实在 4.3 中重现。 -
当然是行为上的改变;您的代码取决于一个错误,并且该错误已得到修复。从未记录过命令修饰符会影响参数或重定向到命令,只有发生命令查找和执行的环境。