如何将参数传递给source命令调用的脚本?

时间:2016-09-29 11:13:05

标签: linux bash

我通过source命令调用脚本,并希望将参数传递给脚本。

我检查了man source,bash返回:

  

:[参数]
                没有效果;除扩展参数和执行任何指定的重定向之外,该命令不执行任何操作。返回零退出代码。

     

源文件名[参数]
                在当前shell环境中从filename读取并执行命令,并返回从filename执行的最后一个命令的退出状态。如果filename不包含斜杠,则使用PATH中的文件名来查找包含filename的目录。在PATH中搜索的文件不需要是可执行的。当bash不处于posix模式时,如果在PATH中找不到文件,则搜索当前目录。如果关闭shopt内置命令的sourcepath选项,则不搜索PATH。如果提供了任何参数,则在执行文件名时它们将成为位置参数。否则,位置参数不变。返回状态是脚本中退出的最后一个命令的状态(如果没有执行命令,则为0),如果找不到或无法读取文件名,则返回false。

它没有例子,所以我不明白。

3 个答案:

答案 0 :(得分:5)

使用以下内容创建文件test.sh

echo "I was given $# argument(s):"
printf "%s\n" "$@"

然后从交互式shell会话中获取它:

$ source ./test.sh a 'b c'
I was given 2 argument(s):
a
b c

因此您可以像使用$@$1$2$3等常规bash脚本一样访问参数。

为了进行比较,请将其作为常规脚本运行:

$ bash ./test.sh a 'b c'
I was given 2 argument(s):
a
b c

答案 1 :(得分:2)

扩展来自 redneb 的(当前接受的)答案...

TL;DR 需要在另一个脚本中获取一个没有位置参数的脚本?试试 function DoSource() { source test.sh ; } ; DoSource 而不是 source test.sh

source在另一个脚本中编写一个没有参数的脚本

问题中 Bash 手册的摘录显示了如何将位置参数分配给源脚本的详细信息。特别是,如果源命令没有指定任何参数,它会被分配来自调用环境的参数。

结果是在另一个脚本中source一个脚本不传递参数可能会很麻烦。 例如,让我们使用 redneb 示例作为 test.sh:

echo "I was given $# argument(s):"
printf "%s\n" "$@"

源自另一个脚本 userScript.sh,例如单线:

source test.sh

运行上述示例时:

$ bash userScript.sh a 'b c'
I was given 2 argument(s):
a
b c

test.sh 继承了 userScript.sh 位置参数...现在不是我想要的(如果我这样做了,我可以使用 source test.sh "$@")。

我发现以下是一个有用的解决方法:将源命令封装到 Bash 函数中。新的 userScript.sh 看起来像:

function DoSource() { source test.sh ; }
DoSource

报告:

$ bash userScript.sh a 'b c'
I was given 0 argument(s):

请注意,指定空参数 (source test.sh '') 并不等效,因为空参数将传递给 test.sh

如果采购脚本也需要采购

如果 userScript.sh 本身应该是来源,那么人们可能不想留下 DoSource()。在这种情况下,简单的解决方案是自毁:

function _userScript_sh_DoSource() { source test.sh ; unset "$FUNCNAME" ; }
_userScript_sh_DoSource

一次性使用(已选择函数名称以减少名称冲突的可能性);或者 unset _userScript_sh_DoSource 命令可以放在不再需要 _userScript_sh_DoSource 之后。

多种用途的灵活变体

更复杂的 DoSource() 变体:

function DoSource() { local ScriptName="$1" ; shift ; source "$ScriptName" ; }
DoSource test1.sh
DoSource test1.sh "$@"
DoSource test2.sh

可以用作 source 的“插入式”替代品,唯一的区别是当没有为要获取的脚本指定位置参数时,source 会继承它们,而 { {1}} 不使用。 但请注意,DoSource 是一个函数,因此在其他方面(例如堆栈调用、DoSource、...)的行为与 source 不同。

答案 2 :(得分:0)

Bourne外壳程序和其他一些外壳程序忽略传递给“”的参数。 (请参阅https://unix.stackexchange.com/questions/5024/passing-variables-to-a-bash-script-when-sourcing-it)。

我可以提出一种解决方法。假设您要获取的脚本看起来像这样:

$ cat ./setEnv 
export BRANCH=$0
export TARGET=$1

它通常不起作用:

$ sh -c '. ./setEnv master linux; echo BRANCH=$BRANCH ; echo TARGET=$TARGET'
BRANCH=sh
TARGET=

但是,如果您在''之后指定参数,则它们将属于父外壳,可以在您正在采购的脚本中访问它们:

$ sh -c '. ./setEnv; echo BRANCH=$BRANCH ; echo TARGET=$TARGET' master linux
BRANCH=master
TARGET=linux

当我在Bourne shell中需要一个单行命令时使用这种方式,该命令以“ ../setEnv”开头,并以多个命令分隔;或&&。