diferença entre / bin / bash e “.”

4

Env: Ubuntu 14.04

Eu tenho um arquivo chamado bc na minha pasta pessoal. Todo o conteúdo do arquivo é

func() {
    local a b=()
    echo $0
}
func

Não há #!/bin/bash no começo.

Então, se eu fizer /bin/bash ~/bc , obtenho

/home/dev/bc

como esperado.

No entanto, se eu usar a fonte . ~/bc , recebo o seguinte erro:

bash: /home/dev/bc: line 2: syntax error near unexpected token '('
bash: /home/dev/bc: line 2: '    local a b=()'

Estou assumindo que um shell diferente é executado para o sourcing. Se for esse o caso, então como posso alterá-lo?

Se eu fizer um chsh , obtenho

dev@c1:~$ sudo chsh
[sudo] password for dev: 
Changing the login shell for root
Enter the new value, or press ENTER for the default
    Login Shell [/bin/bash]: 

------ dos comentários --------

echo $SHELL retorna /bin/bash

    
por Alexandre Santos 12.05.2015 / 20:59

1 resposta

4

O problema é quase definitivamente um alias. Quando você faz:

/bin/bash somefile

Você carrega um novo shell. Você começa um novo começo. Esse executável não é sobrecarregado com todas as coisas que você coloca em seus arquivos de inicialização - rc s - porque eles são apenas originados por padrão para shells interativos, o que é não mencionar nenhuma lógica adicional acumulada desde então.

Aliases são estranhos. Os aliases são expansões do analisador - eles são o primeiro tipo de objeto expansível que a maioria dos shells suporta e são expandidos de formas que muitos não esperam. O bash , na verdade, desencoraja seu uso - por qualquer motivo - desabilitando alias de expansões por padrão em qualquer shell não interativo. E assim, se um alias causar esse erro - e tenho certeza de que esse é o problema -, até mesmo o fornecimento de seus arquivos de ambiente provavelmente ainda não obterá a mesma saída de erro quando você /bin/bash .

Quando digo que aliases são estranhos, é porque eles são expandidos em um nível diferente de outros tipos de expansões de shell. Provavelmente isso é mais óbvio em um contexto de definição de função; em que nenhuma expansão de shell ocorre - já que elas são reservadas para a execução posterior da função - exceto aliases sem avaliar duas vezes a expressão. E os aliases são nunca expandidos durante execução da função (novamente, curto em eval ) , porque já eram expandido durante a sua definição.

Veja um exemplo:

alias a='echo not a;b'
b(){ echo a\?; }; a(){ echo le sigh...; }
a; b

... imprime ...

not a
not a
le sigh...
le sigh...

A primeira vez que o alias chamado a é expandido é quando eu faço:

a(){...

Isso é possível porque os () parens são tokens de shell - não são palavras reservadas como {} - e podem delimitar uma palavra sem espaço em branco - o que os torna particularmente úteis para funções como declarações de função e matriz conforme o analisador executa expansão macro para chegar a uma instrução executável. O resultado da expansão acima é ...

}; echo not a;b(){ 

A última vez que é expandida transforma:

a; b

... em ...

echo not a;b; b

Veja, expansões típicas de shell ocorrem em um contexto pré-delimitado - elas são limitadas por todos os lados por operadores de controle como:

\n[]{}|&();<>\'"'

Desta forma, a maioria das expansões de shell servem como um mecanismo de cotação em si - aspas expandidas de uma variável não delimitam recursivamente contextos citados porque a expansão as citou. A expansão do alias ocorre antes disso, porém - os aliases são expandidos se reconhecidos pelo analisador enquanto ele verifica a primeira palavra do shell em um comando simples - antes de digitalizar no restante dele. Então, se a expansão resultar em mais de um simples comando simples, bem ... então que assim seja.

Minha suposição é que você tem um alias declarado para func - essa seria a explicação mais simples - mas porque os aliases podem encadear se forem definidos com um espaço à direita - e também serão expandidos uma definição de função - não há como saber com certeza apenas as informações que você fornece. Eu acho que posso reproduzir seu erro, no entanto. Isso está próximo:

alias func='func('
func(){
    local a b=()
    echo $0
}
func

... que imprime ...

bash: syntax error near unexpected token '('
bash: local: can only be used in a function
bash
bash: syntax error near unexpected token '}'
bash: syntax error near unexpected token 'newline'

Então faça:

alias func local a b echo

E deixe-nos saber.

    
por 13.05.2015 / 00:48

Tags