假设我有一个名为test.sh的shell / bash脚本:
#!/bin/bash
TESTVARIABLE=hellohelloheloo
./test2.sh
我的test2.sh是这样的:
#!/bin/bash
echo ${TESTVARIABLE}
这行不通。我不想将所有变量作为参数传递,因为这是多余的。
还有别的办法吗?
假设我有一个名为test.sh的shell / bash脚本:
#!/bin/bash
TESTVARIABLE=hellohelloheloo
./test2.sh
我的test2.sh是这样的:
#!/bin/bash
echo ${TESTVARIABLE}
这行不通。我不想将所有变量作为参数传递,因为这是多余的。
还有别的办法吗?
当前回答
除了致命错误的答案之外,还有一种方法可以将变量传递给另一个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"
发生这种情况的原因在本链接中有恰当的描述
其他回答
你基本上有两个选择:
在执行第二个脚本之前,将该变量设置为环境变量(export TESTVARIABLE)。 来源第二个脚本,即。Test2.sh和它将在同一个shell中运行。这将允许您轻松地共享更复杂的变量(如数组),但也意味着其他脚本可以修改源shell中的变量。
更新:
使用export来设置一个环境变量,你可以使用一个已经存在的变量:
A=10
# ...
export A
这应该在bash和sh中都可以工作。bash还允许它像这样组合:
export A=10
这也适用于我的sh(恰好是bash,你可以使用echo $SHELL检查)。但我不相信这在所有sh中都能保证工作,所以最好安全地将它们分开。
以这种方式导出的任何变量都将在你执行的脚本中可见,例如:
a.sh:
#!/bin/sh
MESSAGE="hello"
export MESSAGE
./b.sh
b.sh:
#!/bin/sh
echo "The message is: $MESSAGE"
然后:
$ ./a.sh
The message is: hello
这两个脚本都是shell脚本,这也是偶然的。环境变量可以传递给你执行的任何进程,例如,如果我们使用python来代替它,它可能是这样的:
a.sh:
#!/bin/sh
MESSAGE="hello"
export MESSAGE
./b.py
b.py:
#!/usr/bin/python
import os
print 'The message is:', os.environ['MESSAGE']
采购:
相反,我们可以这样做:
a.sh:
#!/bin/sh
MESSAGE="hello"
. ./b.sh
b.sh:
#!/bin/sh
echo "The message is: $MESSAGE"
然后:
$ ./a.sh
The message is: hello
这或多或少直接“导入”b.sh的内容,并在同一个shell中执行它。注意,我们不需要导出变量来访问它。这将隐式地共享您拥有的所有变量,并允许其他脚本在shell中添加/删除/修改变量。当然,在这个模型中,两个脚本应该使用相同的语言(sh或bash)。举个例子,我们可以来回传递消息:
a.sh:
#!/bin/sh
MESSAGE="hello"
. ./b.sh
echo "[A] The message is: $MESSAGE"
b.sh:
#!/bin/sh
echo "[B] The message is: $MESSAGE"
MESSAGE="goodbye"
然后:
$ ./a.sh
[B] The message is: hello
[A] The message is: goodbye
这在bash中同样有效。它还可以方便地共享无法表示为环境变量的更复杂的数据(至少不需要您做一些繁重的工作),如数组或关联数组。
在Bash中,如果你在子shell中导出变量,使用括号,你可以避免泄漏导出的变量:
#!/bin/bash
TESTVARIABLE=hellohelloheloo
(
export TESTVARIABLE
source ./test2.sh
)
这样做的好处是,在你从命令行运行脚本之后,你不会看到$TESTVARIABLE泄露到你的环境中:
$ ./test.sh
hellohelloheloo
$ echo $TESTVARIABLE
#empty! no leak
$
实际上,有一种比导出和取消设置或再次获取更简单的方法(至少在bash中是这样,只要你愿意手动传递环境变量):
随他去吧
#!/bin/bash
secret="winkle my tinkle"
echo Yo, lemme tell you \"$secret\", b.sh!
Message=$secret ./b.sh
b.sh是
#!/bin/bash
echo I heard \"$Message\", yo
观察到的输出为
[rob@Archie test]$ ./a.sh 哟,让我告诉你"去我的丁丁",混蛋! 我听到了"撸我的丁丁
神奇之处在于a.h sh的最后一行,其中Message仅在调用./ b.h sh期间被设置为a.h sh的secret值。 基本上,它有点像命名参数/参数。不仅如此,它甚至还适用于$DISPLAY这样的变量,用于控制应用程序在哪个X Server中启动。
记住,环境变量列表的长度不是无限的。在我使用相对普通内核的系统上,xargs——show-limits告诉我参数缓冲区的最大大小是2094486字节。从理论上讲,如果您的数据大于此值(管道,有人吗?),则使用shell脚本是错误的。
另一种更简单的方法是使用命名管道。命名管道提供了一种在不同进程之间同步和发送消息的方法。
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语言编写的命令。