为什么这个Bash脚本不能继承所有环境变量?

时间:2018-07-10 19:02:13

标签: bash

我正在尝试一些非常简单的方法:

PEOPLE=(
  "nick"
  "bob"
)
export PEOPLE="$(IFS=, ; echo "${PEOPLE[*]}")"
echo "$PEOPLE"  # prints 'nick,bob'
./process-people.sh

由于某些原因,process-people.sh没有看到$PEOPLE。与之类似,如果我从echo "$PEOPLE"内部process-people.sh来打印空白行。

据我了解,通过调用./process-people.sh创建的子进程应该继承所有父进程的环境变量,包括$PEOPLE。  但是,我已经在Bash 3.2.57(1)-发行版和4.2.46(2)-发行版上进行了尝试,但这不起作用。

这是怎么回事?

1 个答案:

答案 0 :(得分:3)

对于joining the elements of a Bash array into a string,这是一个很好的解决方案。您是否知道在Bash中您cannot export array variables to the environment?如果环境中没有变量,则子进程将看不到它。

啊。但是,您不是要导出数组,而是。您正在将数组转换为字符串,然后将其导出。所以应该可以。

但这是Bash!在各种历史事故共同企图的地方。

正如@PesaThe和@chepner在下面的注释中指出的那样,您实际上不能将Bash数组变量转换为字符串变量。根据{{​​3}}:

  

引用没有下标的数组变量等效于引用下标0。

因此,当您调用export PEOPLE=...时,先前为PEOPLE分配了一个数组值,那么您实际要做的就是PEOPLE[0]=...。这是一个更完整的示例:

PEOPLE=(
  "nick"
  "bob"
)
export PEOPLE="super"
echo "$PEOPLE"  # masks the fact that PEOPLE is still an array and just prints 'super'
echo "${PEOPLE[*]}"  # prints 'super bob'

不幸的是,export默默地未能将数组导出到环境(它返回0),并且在某些情况下Bash将ARRAY_VARIABLE等同于ARRAY_VARIABLE[0]令人困惑情况。我们只需要考虑到历史和向后兼容性的组合。

这是解决您问题的有效方法:

PEOPLE_ARRAY=(
  "nick"
  "bob"
)
export PEOPLE="$(IFS=, ; echo "${PEOPLE_ARRAY[*]}")"
echo "$PEOPLE"  # prints 'nick,bob'
./process-people.sh

此处的关键是将数组和派生的字符串分配给不同的变量。由于PEOPLE是适当的字符串变量,因此它将很好地导出并且process-people.sh可以正常工作如预期的那样。

不可能直接将Bash数组变量更改为字符串变量。一旦为变量分配了数组值,它将成为数组变量。将其更改回字符串变量的唯一方法是使用unset将其销毁并重新创建。

Bash有一些方便的命令,可用于检查变量,这些变量对于调查此类问题非常有用:

printenv PEOPLE  # prints 'nick,bob'
declare -p PEOPLE_ARRAY  # prints: declare -ax PEOPLE_ARRAY='([0]="nick" [1]="bob")'

printenv将仅返回环境变量的值,而echo将返回环境变量的值,无论该变量是否已正确导出。

declare -p将显示变量的完整值,而不会涉及包含或不包含数组索引引用(例如ARRAY_VARIABLE[*])的陷阱。