从别名定义调用 Bash 函数

从别名定义调用 Bash 函数

我正在使用 Xilinx ISE,该程序需要获取供应商脚本来设置其所有工具的路径。由于此脚本破坏了 shell 的某些功能,因此我不想在 shell 启动时获取它,而是仅在需要时才获取它。

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

alias p1='source /long/path/;unalias p1;...;unalias pn;p1'

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

以下是我的相关部分.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"`

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

function iseAlias() {
  alias $1='setupise;'`iseAddToRemoveCall $1`
}

不过,我想首先解决我上面描述的问题。当我运行时,问题变得明显type iseRemoveSetup,它输出:

iseRemoveSetup is aliased to `'

答案1

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

别名分析器='setupise;'`iseAddToRemoveCall“分析器”`

对于iseAddToRemoveCall "analyzer"启动的子 shell,别名定义仅影响该子 shell,此行完成后该子 shell 就会消失。

这可以通过改变来解决

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

alias analyzer='setupise;$(iseAddToRemoveCall analyzer)'

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

选择

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

补充说明

man 1 bash:

替换文本的第一个单词会进行别名测试,但与正在扩展的别名相同的单词不会再次扩展。这意味着可以将 ls 别名为 ls -F,并且 bash 不会尝试递归地扩展替换文本。

因此,在调用别名之前,您不需要unalias p1定义别名pi

最好将(关联)数组与您想要取消别名的命令一起使用,然后只使用该数组。

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

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

相关内容