Bash中可能的错误?:foo(){echo“ $ {var [0]}”; }; var =(bar baz)foo


22

作业系统:Ubuntu 16.04.3

外壳:Bash 4.3.48


我知道可以像中那样临时更改变量的内容var=value command,这可能IFS= read -r var是最值得注意的情况。

而且,感谢Greg的Wiki,我也了解:

# Why this
foo() { echo "$var"; }
var=value foo

# And this does work
var=value; echo "$var"

# But this doesn't
var=value echo "$var"

我无法理解的是:

$ foo() { echo "${var[0]}"; }
$ var=(bar baz) foo
(bar baz)

据我所知(按照前面示例的逻辑),它应该打印bar,而不是(bar baz)

这只会发生在我身上吗?这是预期的行为,我缺少什么吗?还是这是一个错误?


3
也许这与bash不支持将数组作为环境变量有关吗?
Jesse_b

3
@Jesse_b也许吧。虽然运行时export var=(foo bar); echo "${var[0]}"可以打印foo,但不能打印(foo bar)
nxnev

1
奇怪的是,这也对我有用。并使用export它显示:declare -ax var=([0]="foo" [1]="bar")
Jesse_b

3
环境不能包含数组AFAIK。例如,export i_am_array=(foo bar); /usr/bin/env | grep i_am_array此处不提供任何输出。
derobert

3
另外:foo() { declare -p var; } ; var=(bar baz) foo提供declare -x var="(bar baz)"确认其被视为字符串而不是数组的方法
derobert

Answers:


19

一般调用:

var=value cmd

cmd函数在哪里是不可移植的。

使用bash,仅适用于标量变量(并且x=(...)解析为数组但指定为标量),如果使用范围定义,则存在很多问题,使用ksh93yash则可行,但变量定义此后仍然保留。使用mksh,您会收到语法错误。在Bourne shell中,它甚至根本不起作用,即使对于标量变量也是如此。

还要注意,即使使用标量变量,变量是否最终在函数中导出(即传递给正在执行的命令)也因外壳而异(在bash,yash,mksh,zsh中,但在ksh中不一样),灰)。

它只能按您期望的方式工作zsh。请注意,zsh数组索引从1开始。

bash-4.4$ zsh
$ a=(before value)
$ f() echo $a[1]
$ a=(temp value) f
temp
$ echo $a[1]
before

12

这不仅是一个错误,而且似乎是一个未实现的功能,没有任何计划可以实现。这封2014年寄出的邮件来自作者:

幸运的是,在bash 4.3(补丁级别25)中,您不能仅使用-DARRAY_EXPORT来获取数组变量的导入/导出。该代码无法编译,如果您对其进行了修复,则它不会链接,并且如果您对其进行了修复,那么最终会遇到以下问题。

为此,要经历很多麻烦。我没有任何启用阵列导出的计划。

从Bash的最新git repo中提取的内容是variables.c

  #  if ARRAY_EXPORT
        /* Array variables may not yet be exported. */

提示那里还没有完成。


5
在这里,它是针对一个函数的,因此不存在任何导出问题,因为不execve()涉及系统调用。请参阅参考资料zsh中的shell,该shell支持以这种方式临时设置的数组调用函数。
斯特凡Chazelas

@StéphaneChazelas但是,环境会发生变化(通过添加新变量),然后在函数完成后恢复到原来的状态(我就是这种情况:)my_var=one func_bar。我们可以说这export增加了环境,因此在引擎盖下使用了出口吗?看我的答案,我添加了演示代码。
MiniMax

10

man bash的BUGS部分(的版本bash为4.3):

臭虫

   Array variables may not (yet) be exported.

下面的代码演示了仅在函数运行时环境中存在临时变量。功能完成后,临时变量消失。

### defining the "bar" function
### it pass all environment variables to the "grep" command
### and the "grep" prints the only "my_var" variable from it
bar() { env | grep my_var=; }

### calls the "bar" function with the temporary 
### variable "my_var" created and assigned.
my_var=one bar

my_var=one         ### The output. The environment contains the "my_var" variable

### checks, does the environment still have the "my_var" variable
### (It doesn't have.)
env | grep my_var=
                   ### The output is empty,
                   ### the environment doesn't contain the "my_var" variable

相关信息:

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.