Os programas invocados pelo shell herdam as variáveis do shell?

2

Se eu tiver este script de shell

str="A tremor in the Force.
The last time I felt it was in the presence of my old master."

cat <<< "$str"

Meu entendimento é que o comando

cat <<< "$str"

diz ao shell para invocar o programa /bin/cat e passar o argumento $str - onde as aspas duplas em torno de $str asseguram que o shell passará o argumento inalterado. Portanto, se o programa cat obtiver a variável $str inalterada, ela deverá estar ciente do valor das variáveis? Minha pergunta é: o shell passa variáveis declaradas em seu ambiente para outros programas do sistema que ele invoca?

    
por the_velour_fog 05.12.2015 / 21:28

2 respostas

7

Does the shell pass variables declared in its environment to other system programs that it invokes?

Sim, mas não no caso de cat <<< "$str" .

Em sistemas operacionais do tipo Unix, a maioria dos novos programas é executada como resultado do sistema execve() all:

int execve(const char *filename, char *const argv[], char *const envp[]);

O shell usa execv para executar programas e, por padrão, o shell transmite todas as variáveis de ambiente em envp , semelhante à maneira como os argumentos de linha de comando são transmitidos em argv . Conceitualmente, envp é uma sequência de strings, cada uma com o formato NAME=value .

man 2 execve explica todo o processo com muita clareza e inclui código de exemplo de trabalho.

No caso de cat <<<"$str" , o shell fornece "$ str" à entrada padrão de cat on cat , portanto cat nunca vê a variável denominada str , a menos que tenha sido exportada anteriormente por o shell, por exemplo invocando export str , mas cat não tem como saber que os dois estão relacionados.

<<< é um "Here String" e uma extensão do shell. Na página bash man:

The word undergoes brace expansion, tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion, and quote removal. Pathname expansion and word splitting are not performed. The result is supplied as a single string to the command on its standard input.

O Here String é semelhante ao idioma tradicional:

echo "$str" | cat

que eu recomendo. Ambos, de fato, adicionarão uma nova linha no final da entrada padrão. Eu acredito que ambos os métodos são idênticos, desde que echo não modifique a saída de qualquer forma (o que pode depender do conteúdo da string, então uma versão mais segura é printf '%s' "$str" em vez de echo ).

Na sua situação, eu usaria printf '%s' "$str" | cat porque é o mais portátil, universal e de fácil compreensão, sem bloquear o seu script para execução com apenas um dos muitos shells. Se você usar a página POSIX sh man para sua documentação do shell script, você terá menos material para masterizar, e o material que você aprende tem aplicação em todos os derivados de shell Bourne.

    
por 05.12.2015 / 21:38
5

Os programas invocados por um shell não herdam as variáveis do shell. Eles apenas herdam variáveis de ambiente. Uma variável é colocada no ambiente se você escrever export str (ou de algumas formas menos comuns), não se você apenas atribuir a ela.

cat não se importaria com variáveis de ambiente, de qualquer forma.

O comando cat <<< "$str" não passa nenhum argumento para cat . Invoca cat sem argumento, mas com entrada padrão conectada a um canal no qual o shell grava o valor da variável str mais uma nova linha. O processo cat não vê $str , ele vê A tremor … my old master (com uma nova linha final). As aspas duplas em torno de $str impedem que a divisão e globalização de palavras aconteçam com o valor da variável: "$str" expande para exatamente o valor de str . Você pode estar confundindo aspas duplas com aspas simples - cat <<< '$str' passaria a string de cinco caracteres $str com uma nova linha final como entrada para cat .

    
por 06.12.2015 / 00:19

Tags