shell函数中的“声明”和环境变量的范围

Car*_*ood 1 bash

考虑以下测试片段(这些是文件“declare_test”的内容):

function do_foobar ()
{
  unset FOOBAR
  declare -- FOOBAR="default"
  FOOBAR="override"

  echo "At end of do_foobar: FOOBAR = \"$FOOBAR\""
}
Run Code Online (Sandbox Code Playgroud)

从命令提示符运行 do_foobar 会产生:

$ source declare_test
$ do_foobar
At end of do_foobar: FOOBAR = "override"
$ echo "FOOBAR=\"$FOOBAR\""
FOOBAR=""
Run Code Online (Sandbox Code Playgroud)

换句话说,函数 FOOBAR 内部具有预期值,即“覆盖”,但在函数 FOOBAR 立即被取消设置之后。

如果我们更改 do_foobar 并删除“declare”行,则结果是:

$ do_foobar
At end of do_foobar: FOOBAR = "override"
$ echo "FOOBAR=\"$FOOBAR\""
FOOBAR="override"
Run Code Online (Sandbox Code Playgroud)

所以,现在 FOOBAR 没有被重置。请注意,删除的声明的功能是设置FOOBAR。如果我们不删除声明而是删除“FOOBAR=”override”行,则结果将变为:

$ do_foobar
At end of do_foobar: FOOBAR = "default"
$ echo "FOOBAR=\"$FOOBAR\""
FOOBAR=""
Run Code Online (Sandbox Code Playgroud)

因此,函数执行后 FOOBAR 仍未设置。

最后,如果你只删除未设置的FOOBAR,在调用do_foobar之前给FOOBAR一些值,那么结果是FOOBAR没有改变!因此,尽管有声明行,“取消设置”确实在函数之后有效,但声明本身和后续其他赋值不再因为声明而起作用。

这对我来说是一个问题,因为我想从 PROMPT_COMMAND 调用 shell 函数,该函数通过获取由“declare -p”(存在一长串声明命令)生成的文件来恢复我的环境。显然 bash 不允许在函数内使用声明,但它允许直接设置变量。

这不是一个bug吗?bash 的更高版本中修复了吗?(我有 4.3.48)这个问题是否有解决方法,不需要我更改我想要获取的文件(即该文件存在声明命令,我想保持这种状态)。

iam*_*ser 5

declare限制函数内变量的范围,类似于local。如果您想覆盖范围,请使用-g.

#!/bin/bash

function do_foobar ()
{
    unset FOOBAR
    declare -g FOOBAR="default"
    FOOBAR="override"

    echo "At end of do_foobar: FOOBAR = \"$FOOBAR\""
}
Run Code Online (Sandbox Code Playgroud)

$ source test.sh
$ do_foobar
At end of do_foobar: FOOBAR = "override"
$ echo "$FOOBAR"
override
Run Code Online (Sandbox Code Playgroud)