Gerando comandos com expansão de variáveis em um loop

4

Eu quero criar aliases locais enquanto trabalho em determinados diretórios. Por exemplo, eu gostaria de ter o seguinte em um arquivo chamado local_alias

alias foo='bar'

Eu queria escrever um script de limpeza para remover esses aliases depois que eu terminasse de trabalhar. Algo como:

egrep "alias [[:alnum:]]+" local_alias -o|while read i; do
  un$i
done

Se eu alterar a linha do meio para echo un$i , a saída será o que parece ser um comando unalias formatado corretamente: unalias foo . Mas, como escrito, recebo unalias: foo: not found .

Se eu tentar citar a linha do meio: "un$i" , em vez disso, obtenho unalias foo: command not found .

O que estou fazendo de errado?

    
por jake 09.05.2014 / 03:24

2 respostas

3

Os aliases são específicos para o shell, portanto, quando você executa seu script assim:

#!/bin/bash

...
unalias ....
...

Ele está sendo executado como um shell filho, que normalmente não possui os mesmos aliases. Compondo o problema, você também está lidando com outro problema. Assim que o script terminar, o shell filho cujos aliases foram removidos desaparece, retornando você ao shell pai que ainda tem seus aliases intactos.

Não tenho como saber que os aliases do seu shell atual foram modificados dessa maneira.

Então, como fazer isso?

Você pode construir um alias ou uma função dentro do escopo do próprio shell atual para executar esta ação.

Exemplo

solução de alias

$ alias unalias_local='egrep "alias [[:alnum:]]+" local_alias -o|while read i; do un$i; done'

solução de função

$ function unalias_local { egrep "alias [[:alnum:]]+" local_alias -o | \
    while read i; do un$i; done; }

Problemas com o acima

O OP forneceu essas soluções para essa resposta, que ele afirmou que funcionará em seu cenário. Mas, em geral, você não pode alterar os aliases em uma cadeia de comandos canalizados como este, porque cada pipe invoca um subshell, que não poderá tocar o shell do pai. Então, voltamos ao mesmo problema anterior ao script.

Para contornar isso, você poderia fornecer a lista de aliases como argumentos para um comando.

Exemplo

$ alias ali1="cmd1"
$ alias ali2="cmd2"

Confirme os aliases no nosso shell:

$ alias | grep -E "ali[12]"
alias ali1='cmd1'
alias ali2='cmd2'

Conteúdo de local_alias :

$ cat local_alias 
alias ali1="cmd1"
alias ali2="cmd2"

Este comando irá analisar nossos nomes dos aliases do arquivo local_alias :

$ grep -oP "(?<=alias )([[:alnum:]]+)" local_alias
ali1
ali2

Podemos usá-lo para unalias desses aliases da seguinte forma:

$ unalias $(grep -oP "(?<=alias )([[:alnum:]]+)" local_alias)
$

Agora, quando confirmamos que eles desapareceram:

$ alias | grep -E "ali[12]"
$
    
por 09.05.2014 / 03:37
1

Parece que você está executando esse código em um script separado. Isso não funcionará: você precisa alterar a configuração do shell em execução e não pode fazer isso de outro processo. Este código de limpeza deve estar em uma função definida em seu .bashrc .

Um segundo problema é que o pipe também cria um subprocesso (um subshell). Portanto, se você executar esse código dentro de seu shell interativo, o comando unalias removerá o alias, mas apenas na subcamada. Você precisa de uma abordagem diferente que não execute o comando unalias em um subshell.

Existem várias soluções, mas a mais simples seria criar a lista de aliases e, em seguida, executar o comando unalias uma vez. Os nomes de alias não podem conter caracteres especiais, portanto, a divisão de palavras na lista de aliases será adequada para gerar os argumentos para unalias .

unalias $(egrep -o "alias [[:alnum:]]+" local_alias)
    
por 09.05.2014 / 04:43

Tags