我想在某些目录中工作时创建本地别名。例如,我想在名为的文件中包含以下内容local_alias
alias foo='bar'
我想编写一个清理脚本来在完成工作后删除这些别名。就像是:
egrep "alias [[:alnum:]]+" local_alias -o|while read i; do
un$i
done
如果我将中间行更改为echo un$i
,则输出看起来像格式正确的unalias
命令:unalias foo
。但正如所写,我明白了unalias: foo: not found
。
如果我尝试引用中间行:"un$i"
,我会得到unalias foo: command not found
.
我究竟做错了什么?
答案1
别名是特定于 shell 的,因此当您像这样运行脚本时:
#!/bin/bash
...
unalias ....
...
它作为子 shell 运行,通常不会具有相同的别名。使问题更加复杂的是,您还要处理另一个问题。一旦脚本终止,别名已被删除的子 shell 就会消失,并返回到其别名仍然完好的父 shell。
据我所知,无法以这种方式修改当前 shell 的别名。
那么如何做到这一点呢?
您可以在当前 shell 本身的范围内构造一个别名或函数来执行此操作。
例子
别名解决方案
$ alias unalias_local='egrep "alias [[:alnum:]]+" local_alias -o|while read i; do un$i; done'
函数解
$ function unalias_local { egrep "alias [[:alnum:]]+" local_alias -o | \
while read i; do un$i; done; }
上述问题
OP 为这个答案提供了这些解决方案,他说这些解决方案将在他的场景中发挥作用。但一般来说,您不能像这样更改管道命令链中的别名,因为每个管道都会调用一个子 shell,而该子 shell 将无法触及父 shell。因此,我们又回到了与之前脚本相同的问题。
为了解决这个问题,您可以提供别名列表作为命令的参数。
例子
$ alias ali1="cmd1"
$ alias ali2="cmd2"
在我们的 shell 中确认别名:
$ alias | grep -E "ali[12]"
alias ali1='cmd1'
alias ali2='cmd2'
内容local_alias
:
$ cat local_alias
alias ali1="cmd1"
alias ali2="cmd2"
此命令将从文件中解析我们的别名名称local_alias
:
$ grep -oP "(?<=alias )([[:alnum:]]+)" local_alias
ali1
ali2
我们可以将它用于unalias
这些别名,如下所示:
$ unalias $(grep -oP "(?<=alias )([[:alnum:]]+)" local_alias)
$
现在,当我们确认它们已经消失时:
$ alias | grep -E "ali[12]"
$
答案2
您似乎在单独的脚本中运行此代码。这是行不通的:您需要更改正在运行的 shell 的配置,并且无法从另一个进程执行此操作。此清理代码应该位于您的.bashrc
.
第二个问题是管道还创建一个子进程(子shell)。因此,如果您在交互式 shell 中运行此代码,该unalias
命令将删除别名 - 但仅在子 shell 中。您需要一种不在unalias
子 shell 中运行命令的不同方法。
有多种解决方案,但最简单的一种是构建别名列表,然后运行命令unalias
一次。别名不能包含特殊字符,因此别名列表上的单词分割可以很好地生成unalias
.
unalias $(egrep -o "alias [[:alnum:]]+" local_alias)