繁体   English   中英

bash 4.4没有将变量传递给子shell

[英]bash 4.4 not passing variables to sub-shell

Bash 4.4和4.3在将变量传递到subshel​​l或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,但我无法弄清楚是哪个更改导致了行为的改变。

从2014-12-3的详细变更日志条目中:

subst.c

  • command_substitute :如果在扩展重定向的过程中运行命令替换(expanding_redir == 1) ,请刷新我们作为该命令一部分继承的任何临时环境,因为我们不应访问该临时环境。 由于expanding_redir仅控制对临时环境的访问以进行变量查找和绑定,因此我们可以在子shell中将其关闭

具体来说,添加了以下新代码:

  if (expanding_redir)
    {
      flush_temporary_env ();
      expanding_redir = 0;
    }

......它只是删除的所有内容temporary_env哈希表,防止当被不适当地扩大临时环境变量merge_temporary_env()被调用中execute_simple_command()中重定向相关的扩展。

之所以更改,是因为bash 4.3在本文档中错误地将precommand修饰符应用于命令替换的评估。

IFS=':' TZ=$timezone read hour minute <<EOF
$(date +%H:%M)
EOF

IFSTZ的更改应该read命令本身可见,而对date命令不可见。 上面的应该与

dateStr=$(date +%H:%M)
IFS=':' TZ=$timezone read hour minute <<EOF
$dateStr
EOF

此错误已在bash 4.4中修复,我怀疑这是与此处文档和此处字符串的评估有关的代码的常规审核的一部分。 一些相关的错误已在4.3中修复,但其他错误仍然存​​在。

两种环境之间的差异可能在于是否导出了TZ

(
    export TZ
    IFS=':' TZ=$timezone read hour minute <<EOF
        $(date +%H:%M)
EOF
    echo TZOUTER $hour-$minute
)

(
    IFS=':' TZ=$timezone read hour minute <<EOF
        $(date +%H:%M)
EOF
    echo TZOUTER $hour-$minute
)

编辑为了避免在这里文档内部进行变量扩展,请在EOF周围添加单引号

IFS=':' TZ=$timezone read hour minute <<'EOF'
    $(date +%H:%M)
EOF

但是这里需要扩展shell命令,所以最清晰

(
    TZ=$timezone 
    IFS=':' read hour minute <<EOF
        $(date +%H:%M)
EOF
)

另一个比较不明确,因为参数适用于read命令,但尚不清楚是否应将其应用于heredoc替换

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM