在循环中生成带有变量扩展的命令

在循环中生成带有变量扩展的命令

我想在某些目录中工作时创建本地别名。例如,我想在名为的文件中包含以下内容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)

相关内容