我使用一个脚本(我没有写访问权限)来创建一堆别名来设置环境。我想创建一个 bash 函数来设置我的环境,但似乎别名在函数体中不存在。
这是一个最小的例子:
# aliases.sh
alias fooAlias='echo "this will never work!"'
Run Code Online (Sandbox Code Playgroud)
.
# .bashrc
function setupLotsOfThings() {
source aliases.sh
fooAlias
}
Run Code Online (Sandbox Code Playgroud)
.
现在,如果我只是以aliases.sh交互方式获取源代码,那么事情会按预期进行:
[mycomputer]~/ $ source aliases.sh
[mycomputer]~/ $ fooAlias
this will never work!
Run Code Online (Sandbox Code Playgroud)
但是,如果我改为调用 .bashrc 中定义的函数,则在获取其定义后它无法识别别名:
[mycomputer]~/ $ setupLotsOfThings
-bash: fooAlias: command not found
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?alias在函数中使用时,我对命令的范围有什么遗漏吗?
编辑:我将添加一些超出最小示例的细节,以阐明我正在尝试完成的工作。
对于我的工作,我在集群和/或网格上开发和运行了很多软件。我有几个项目需要完全不同的环境,例如不同的 gcc 版本、特定的软件版本、配置和数据路径以及各种环境变量。管理员提供脚本来设置各种东西,通常是通过定义 shell 函数或别名来调用其他函数或别名或运行各种脚本。对我来说,这是一个黑匣子。
我想用一个命令设置我自己的各种环境。目前,我做这样的事情:
[mycomputer]~/ $ source /some/environment/setup/script.sh
[mycomputer]~/ $ aliasToSetupSomeSoftwareVersion #this was defined in the above
[mycomputer]~/ $ anotherAliasForOtherSoftware
[mycomputer]~/ $ source /maybe/theres/another/script.sh
[mycomputer]~/ $ runSomeOtherSetup # this was defined in the new script
Run Code Online (Sandbox Code Playgroud)
这些命令通常必须按顺序运行。我的想法基本上是将以上几行复制到一个功能块中,但正如原始示例所示,这根本行不通。非常受欢迎的替代解决方法!
ter*_*don 11
另一种解决方案是将这些命令粘贴到文本文件而不是功能块中。就像是:
## This is needed to make the sourced aliases available
## within the script.
shopt -s expand_aliases
source /some/environment/setup/script.sh
aliasToSetupSomeSoftwareVersion
anotherAliasForOtherSoftware
source /maybe/theres/another/script.sh
runSomeOtherSetup
Run Code Online (Sandbox Code Playgroud)
将其保存为setup1.sh您喜欢的任何位置。诀窍是那么源文件,而不是执行它:
$ source setup1.sh
Run Code Online (Sandbox Code Playgroud)
这将运行脚本中的别名,并使它们可用于您当前的 shell。
您可以通过将其添加到您的.bashrc:
alias setupLotsOfThings="source setup1.sh"
Run Code Online (Sandbox Code Playgroud)
现在您可以简单地运行setupLotsOfThings并从函数中获得您想要的行为。
这里有两个问题。首先,别名对声明它们的函数不可用,但只有在该函数退出后才可用,其次,别名在脚本中不可用。两者都在 的同一部分中进行了解释man bash:
当 shell 不是交互式时,别名不会扩展,除非使用 shopt 设置 expand_aliases shell 选项(请参阅下面的 SHELL BUILTIN COMMANDS 下的 shopt 描述)。
有关别名的定义和使用的规则有些令人困惑。在执行该行上的任何命令之前,Bash 总是至少读取一行完整的输入。别名在读取命令时展开,而不是在执行时展开。因此,与另一个命令出现在同一行上的别名定义在读取下一行输入之前不会生效。该行别名定义后面的命令不受新别名的影响。执行函数时,此行为也是一个问题。 别名在读取函数定义时展开,而不是在执行函数时展开,因为函数定义本身就是一个复合命令。因此,函数中定义的别名在
执行该函数之前不可用。 为了安全起见,始终将别名定义放在单独的行上,并且不要在 com? 磅命令。
然后,执行和获取文件之间存在差异。基本上,运行脚本使其在单独的 shell 中运行,而 source 它使其在当前 shell 中运行。因此,sourcessetup.sh使别名对父 shell 可用,而作为脚本执行则不行。
实际上,您的别名在函数加载后可用!您可以在交互式 shell 中使用它们,也可以.bashrc在执行函数后使用它们。
限制是函数定义中的别名在读取函数定义时展开,而不是在计算函数时展开。这是 bash 的一个限制。所以这将起作用:
function setupLotsOfThings() {
source aliases.sh
}
setupLotsOfThings
fooAlias
Run Code Online (Sandbox Code Playgroud)
但不是这个:
function setupLotsOfThings() {
source aliases.sh
}
function useTheAliases() {
fooAlias
}
setupLotsOfThings
useTheAliases
Run Code Online (Sandbox Code Playgroud)
如果您需要在函数内部可用并且可以在解析函数后定义的别名,请将它们改为函数。请记住,您可以使用command内置函数从同名函数中调用外部命令。