给出以下可获取的bar
Bash 脚本...
echo :$#:"$@":
...以及以下可执行foo
Bash 脚本:
echo -n source bar:
source bar
echo -n source bar foo:
source bar foo
function _import {
source "$@"
}
echo -n _import bar:
_import bar
echo -n _import bar foo:
_import bar foo
运行 Bash 脚本时得到以下输出foo
,即./foo
:
source bar::0::
source bar foo::1:foo:
_import bar::1:bar:
_import bar foo::1:foo:
这是我的问题:
source
为什么当我从函数调用 Bash 的命令_import
而不是直接调用时会有不同?- 如何规范 Bash
source
命令的行为?
我在 Fedora 版本 20 上使用 Bash 版本 4.2.47(1)-release。
答案1
问题是因为source
在当前环境中执行文件。在 中bash
,如果未提供位置参数,则它们不会更改。从bash
Bourne Shell 内置函数手册页:
。 (一段时间)
。文件名[参数]
在当前 shell 上下文中从文件名参数读取并执行命令。如果文件名不包含斜杠,则使用 PATH 变量来查找文件名。当 Bash 不处于 POSIX 模式时,如果在 $PATH 中找不到文件名,则会搜索当前目录。如果提供任何参数,它们将在执行 filename 时成为位置参数。否则位置参数不变。返回状态是最后执行的命令的退出状态,如果没有执行命令则为零。如果未找到文件名或无法读取文件名,则返回状态为非零。这个内置函数相当于源代码。
POSIX 定义点(是insource
的同义词):dot
bash
shell 应在当前环境中执行文件中的命令。
它还解释了 KornShell 版本的 dot 可以采用可选参数,这些参数设置为位置参数:
KornShell 版本的 dot 采用设置为位置参数的可选参数。这是一个有效的扩展,允许点脚本的行为与函数相同。
因此,当您调用source bar
内部_import
函数时,您不提供任何位置参数,因此它们不会改变。它们与_import
函数作用域相同,$@
包含bar
和$#
是1
(因为你运行_import bar
)。
当您在函数作用域source bar
之外调用时_import
,它与全局作用域(或foo
脚本)相同。在这种情况下,因为您运行./foo
,所以您运行时foo
没有任何参数,$@
为 null 且$#
为零。
答案2
Gnouc 的回答解释了我的第一个问题:“为什么当我从 _import 函数调用 Bash 的源命令而不是直接调用时会有所不同?”
关于我的第二个问题:“如何规范 Bash 源命令的行为?”
我想我找到了以下答案:
通过将_import
函数更改为:
function _import {
local -r file="$1"
shift
source "$file" "$@"
}
运行 Bash 脚本时得到以下输出foo
,即./foo
:
source bar::0::
source bar foo::1:foo:
_import bar::0::
_import bar foo::1:foo:
我的问题和这个答案背后的基本原理:“导入的”Bash 脚本应该能够通过 Bash 的位置和特殊参数来评估自己的参数集,即使在导入时没有给出任何参数。任何可以传递给导入 Bash 脚本的参数都不能隐式传递给导入的 Bash 脚本。