假设我有一个名为test.sh的shell / bash脚本:

#!/bin/bash

TESTVARIABLE=hellohelloheloo
./test2.sh

我的test2.sh是这样的:

#!/bin/bash

echo ${TESTVARIABLE}

这行不通。我不想将所有变量作为参数传递,因为这是多余的。

还有别的办法吗?


当前回答

另一种更简单的方法是使用命名管道。命名管道提供了一种在不同进程之间同步和发送消息的方法。

A.bash:

#!/bin/bash
msg="The Message"
echo $msg > A.pipe

B.bash:

#!/bin/bash
msg=`cat ./A.pipe`
echo "message from A : $msg"

用法:

$ mkfifo A.pipe #You have to create it once
$ ./A.bash & ./B.bash # you have to run your scripts at the same time

B.bash将等待消息,一旦A.bash发送消息,B.bash将继续其工作。

其他回答

另一个选项是使用eval。这只适用于字符串是可信的。第一个脚本可以回显变量赋值:

回声“VAR = myvalue "

然后:

Eval $(./first.sh) ./second.sh

当您想要为其设置环境变量的第二个脚本不在bash中,并且您也不想导出变量时,这种方法特别有用,这可能是因为它们很敏感,您不想让它们持久保存。

在Bash中,如果你在子shell中导出变量,使用括号,你可以避免泄漏导出的变量:

#!/bin/bash

TESTVARIABLE=hellohelloheloo
(
export TESTVARIABLE    
source ./test2.sh
)

这样做的好处是,在你从命令行运行脚本之后,你不会看到$TESTVARIABLE泄露到你的环境中:

$ ./test.sh
hellohelloheloo
$ echo $TESTVARIABLE
                            #empty! no leak
$

另一种更简单的方法是使用命名管道。命名管道提供了一种在不同进程之间同步和发送消息的方法。

A.bash:

#!/bin/bash
msg="The Message"
echo $msg > A.pipe

B.bash:

#!/bin/bash
msg=`cat ./A.pipe`
echo "message from A : $msg"

用法:

$ mkfifo A.pipe #You have to create it once
$ ./A.bash & ./B.bash # you have to run your scripts at the same time

B.bash将等待消息,一旦A.bash发送消息,B.bash将继续其工作。

致命错误给出了一个简单的可能性:来源您的第二个脚本!如果你担心这第二个脚本可能会改变你的一些宝贵的变量,你可以在一个子shell中获取它:

( . ./test2.sh )

括号将使源代码发生在子shell中,这样父shell就不会看到test2.sh可以执行的修改。


这里还应该引用另一种可能性:使用set -a。

从POSIX集合引用:

-a: When this option is on, the export attribute shall be set for each variable to which an assignment is performed; see the Base Definitions volume of IEEE Std 1003.1-2001, Section 4.21, Variable Assignment. If the assignment precedes a utility name in a command, the export attribute shall not persist in the current execution environment after the utility completes, with the exception that preceding one of the special built-in utilities causes the export attribute to persist after the built-in has completed. If the assignment does not precede a utility name in the command, or if the assignment is a result of the operation of the getopts or read utilities, the export attribute shall persist until the variable is unset.

Bash手册:

-a:标记已修改或创建用于导出到后续命令环境的变量和函数。

在你的例子中:

set -a
TESTVARIABLE=hellohelloheloo
# ...
# Here put all the variables that will be marked for export
# and that will be available from within test2 (and all other commands).
# If test2 modifies the variables, the modifications will never be
# seen in the present script!
set +a

./test2.sh

 # Here, even if test2 modifies TESTVARIABLE, you'll still have
 # TESTVARIABLE=hellohelloheloo

注意,规范只指定使用set -a将变量标记为导出。那就是:

set -a
a=b
set +a
a=c
bash -c 'echo "$a"'

将回显c,而不是空行或b(也就是说,set +a不会为导出取消标记,也不会仅为导出的环境“保存”赋值)。当然,这是最自然的行为。

结论:使用set -a/set +a比手动导出所有变量要简单得多。它优于源第二个脚本,因为它可以用于任何命令,而不仅仅是用相同的shell语言编写的命令。

除了致命错误的答案之外,还有一种方法可以将变量传递给另一个shell脚本。

上述建议的解决方案有一些缺点:

使用Export:这将导致变量出现在它们的作用域之外,这不是一个好的设计实践。 使用源:它可能会导致名称冲突或意外覆盖预定义变量在其他一些shell脚本文件,这些文件已经引用了另一个文件。

还有另一种简单的解决方法可供我们使用。 考虑到你发布的例子,

test.sh

#!/bin/bash

TESTVARIABLE=hellohelloheloo
./test2.sh "$TESTVARIABLE"

test2.sh

#!/bin/bash

echo $1

输出

hellohelloheloo

同样重要的是,如果我们传递多字字符串,“”是必要的。 再举一个例子

master.sh

#!/bin/bash
echo in master.sh
var1="hello world"
sh slave1.sh $var1
sh slave2.sh "$var1"
echo back to master

slave1.sh

#!/bin/bash
echo in slave1.sh
echo value :$1

slave2.sh

#!/bin/bash
echo in slave2.sh
echo value : $1

输出

in master.sh
in slave1.sh
value :"hello
in slave2.sh
value :"hello world"

发生这种情况的原因在本链接中有恰当的描述