从别名定义调用 Bash 函数

ted*_*ted 7 bash alias

我正在使用 Xilinx ISE,该程序需要提供供应商脚本来为其所有工具设置路径。由于这个脚本破坏了我的 shell 的一些功能,我不想在 shell 的开始时提供它,而是只在我需要它的时候。

为此,我为source /long/path/to/script. 为方便起见,我希望程序提供的工具在没有安装脚本的情况下始终可以工作。想法是为 n 个程序中的每一个使用如下别名(为了举例,假设它们被命名为 p1,...,pn)

alias p1='source /long/path/;unalias p1;...;unalias pn;p1'
Run Code Online (Sandbox Code Playgroud)

由于有很多程序,我想简化 unalias 链的更新。想法是有alias iseRemoveSetup='unalias p1;...;pn'。为了使程序别名的构建iseRemoveSetup更容易,我定义了一些函数。但是,如果我iseAddToRemoveCall从别名命令(此处为analyzer)调用,它没有任何效果。如果我直接在外壳上调用它,但是它工作正常。

以下是我的相关部分.bashrc

alias iseRemoveSetup=''
function iseAddToRemove() {
  alias iseRemoveSetup=`(alias iseRemoveSetup | cut -f2 -d "'")`"unalias $1;"
}
function iseAddToRemoveCall() {
  iseAddToRemove $1
  echo "iseRemoveSetup;$1"
}

alias setupise='source /home/ted/Xilinx/tools/14.7/ISE_DS/settings64.sh'
alias analyzer='setupise;'`iseAddToRemoveCall "analyzer"`
Run Code Online (Sandbox Code Playgroud)

我知道拥有这样的功能是一个想法:

function iseAlias() {
  alias $1='setupise;'`iseAddToRemoveCall $1`
}
Run Code Online (Sandbox Code Playgroud)

但是我想先解决我上面描述的问题。当我运行时type iseRemoveSetup,问题变得可见,它输出:

iseRemoveSetup is aliased to `'
Run Code Online (Sandbox Code Playgroud)

Hau*_*ing 5

问题是您的别名定义(其中之一iseRemoveSetup)在子shell中:

alias Analyzer='setupise;'`iseAddToRemoveCall "analyzer"`

因为iseAddToRemoveCall "analyzer"启动了一个子shell,并且别名定义只影响这个子shell,这行一完成它就消失了。

这可以通过改变来解决

alias analyzer='setupise;'`iseAddToRemoveCall "analyzer"`
Run Code Online (Sandbox Code Playgroud)

alias analyzer='setupise;$(iseAddToRemoveCall analyzer)'
Run Code Online (Sandbox Code Playgroud)

并将echo "iseRemoveSetup;$1"(in iseAddToRemoveCall)替换为echo "unalias $1;$1". 因此unalias将成为别名扩展的一部分并在正确的 shell 中执行。

选择

这一切对我来说似乎很奇怪。启动子shell(type bash),运行安装程序,运行命令,并^D在完成后离开子shell()不是更有意义吗?

补充说明

man 1 bash

替换文本的第一个单词会测试别名,但与被扩展的别名相同的单词不会被第二次扩展。这意味着可以将 ls 别名为 ls -F,例如,bash 不会尝试递归扩展替换文本。

所以你不需要unalias p1在你的别名定义中调用pi它。

将(关联)数组与要取消别名的命令一起使用可能更好,并且只使用该数组。

这也很重要,因为你做了你不应该做的事情:

在执行该行上的任何命令之前,Bash 总是至少读取一行完整的输入。别名在读取命令时展开,而不是在执行时展开。因此,与另一个命令出现在同一行上的别名定义在读取下一行输入之前不会生效。该行别名定义后面的命令不受新别名的影响。执行函数时,此行为也是一个问题。别名在读取函数定义时展开,而不是在执行函数时展开,因为函数定义本身就是一个复合命令。因此,函数中定义的别名在执行该函数之前不可用。为安全起见,始终将别名定义放在单独的行上,并且不要在复合命令中使用别名。