我调用了以下脚本.bash_functions.test
,该脚本已由我的.bash_functions
脚本提供:
# vim: set syn=sh noet:
mp4Options_BIS="-movflags +frag_keyframe"
declare -A audioExtension=( [libspeex]=spx [speex]=spx [opus]=opus [vorbis]=ogg [aac]=m4a [mp3]=mp3 [mp2]=mp2 [ac3]=ac3 [wmav2]=wma [pcm_dvd]=wav [pcm_s16le]=wav )
function test1 {
echo "=> mp4Options_BIS = $mp4Options_BIS"
echo "=> audioExtension = ${audioExtension[*]}"
}
当我运行该test1
函数时,我看到了这个:
=> mp4Options_BIS = -movflags +frag_keyframe
=> audioExtension =
最后,当我再次获取脚本并重新运行该test1
函数时,我看到了:
=> mp4Options_BIS = -movflags +frag_keyframe
=> audioExtension = ac3 wma opus mp3 wav mp2 wav spx m4a spx ogg
事实上,我Source
在第一个源调用以及source
内置函数和第二个源调用中使用了我的函数:
$ grep -r .bash_functions.test
.bash_functions:source $initDir/.bash_functions.test
$ type Source
Source is a function
Source ()
{
test "$debug" -gt 0 && time source "$@" && echo || source "$@"
}
这就是发生的事情:
$ Source .initBash/.bash_functions.test
$ test1
=> mp4Options_BIS = -movflags +frag_keyframe
=> audioExtension =
$ source .initBash/.bash_functions.test
$ test1
=> mp4Options_BIS = -movflags +frag_keyframe
=> audioExtension = ac3 wma opus mp3 wav mp2 wav spx m4a spx ogg
为什么它会这样工作?
declare
/typeset
without-g
除了设置类型之外,还声明当前范围内的变量。在这里,因为
declare -A audioExtension=(...)
最终在函数内运行Source
,这导致audioExtension
变量被声明为该函数的本地变量,因此一旦Source
返回,它的定义就会丢失。您可以将其更改为
typeset -Ag audioExtension=(...)
始终在全局范围内声明变量(它与 zsh/mksh/yash 不同,zsh/mksh/yashtypeset -g
仅阻止将变量设为本地(仅更新类型/属性和值);当您的Source
函数时,它会有所不同从另一个函数本身调用;有关详细信息,请参阅bash vs zsh:范围和 `typeset -g`)。如果您使用
ksh93
而不是bash
(这是外壳bash
借用了关联数组语法),您可以将您的Source
函数定义为:相对于:
在 ksh93 中,使用 Bourne 样式
func() cmd
语法定义的函数没有局部作用域,而function func {
具有静态局部作用域(那里只有一个全局作用域和一个本地每个函数作用域,而不是一堆局部作用域)。在
bash
(和其他具有本地作用域的 shell)中,没有类似的方法可以拥有不引入新作用域的函数。您可以使用如下alias
代替:(请注意,别名在读取代码时扩展,而不是在执行时扩展)。
与您的功能方法相比,它会在功能上有所不同:
我们将对两者都进行计时,
source myfile
并且在函数方法中将other-cmd
其扩展为仅通过计时。time source ./myfile | other-cmd
source ./myfile
使用
source=(time source); "${source[@]}" /some/file
不起作用(它会调用time
独立实用程序而不是bash
time 关键字)。