Qual das seguintes operações de shell é executada dentro do corpo da função ao executar uma definição de função e ao chamar uma função?

0

Uma definição de função é um comando. Quando uma definição de função é executada, eu pensei que o corpo da função seria mantido intacto, como se o corpo da função fosse simples.

Eu sabia que estava errado, quando entendi o seguinte do Manual de Bash em resposta do G-Man para minha alias e funções pergunta:

Aliases are expanded when a function definition is read, not when the function is executed, ….

Portanto, a expansão de alias é executada no corpo da função, enquanto a expansão de parâmetro não é, conforme mostrado no exemplo a seguir:

$ alias myalias=cat
$ echo $var
3
$ myfunc() { myalias myfile; echo $var; }
$ declare -fp myfunc
myfunc () 
{ 
    cat myfile;
    echo $var
}

Da mesma forma, uma chamada para uma função também é um comando.

aliases defined in a function are not available until after that function is executed.

então a definição de alias é executada apenas ao executar, ou seja, chamar a função, não ao executar a definição da função.

expansões de apelidos e execução de definições de alias são apenas duas das operações de shell listadas abaixo.         

Minhas perguntas são:

  1. Quais operações shell são executadas dentro do corpo da função, e quais operações não são executadas,

    • quando está executando uma definição de função ?

    • quando chama uma função , ou seja, executando uma função ?

  2. Existem operações de shell que são executadas durante executando a definição de uma função e chamando a função?

    Ou executar a definição de uma função e chamar a função executar conjuntos não sobrepostos de operações de shell?

As operações possíveis estão listadas na seguinte citação do manual de Bash :

3.1.1 Shell Operation

The following is a brief description of the shell’s operation when it reads and executes a command. Basically, the shell does the following:

  1. Reads its input from a file (see Section 3.8 [Shell Scripts], page 39), from a string supplied as an argument to the -c invocation option (see Section 6.1 [Invoking Bash], page 80), or from the user’s terminal.

  2. Breaks the input into words and operators, obeying the quoting rules described in Section 3.1.2 [Quoting], page 6. These tokens are separated by metacharacters. Alias expansion is performed by this step (see Section 6.6 [Aliases], page 88).

  3. Parses the tokens into simple and compound commands (see Section 3.2 [Shell Commands], page 8).

  4. Performs the various shell expansions (see Section 3.5 [Shell Expansions], page 21), breaking the expanded tokens into lists of filenames (see Section 3.5.8 [Filename Expansion], page 30) and commands and arguments.

  5. Performs any necessary redirections (see Section 3.6 [Redirections], page 31) and removes the redirection operators and their operands from the argument list.

  6. Executes the command (see Section 3.7 [Executing Commands], page 35).

  7. Optionally waits for the command to complete and collects its exit status (see Section 3.7.5 [Exit Status], page 38).

    
por Tim 04.08.2017 / 02:09

1 resposta

2

<rant>
“running a function definition” and “running the definition of a function” are not common idioms.  I expect that most people would refer to that simply as “defining a function”.  OK, that phrase might be interpreted to refer to
  1. conceptually specifying the characteristics and interfaces (parameters and other inputs, processing, and outputs) of a function (this is an activity performed by a person, or a group of people)
  2. choosing the implementation of a function; i.e., what commands to use in the function body.  This is an activity performed by a person, or a group of people, possibly using paper, whiteboards, and/or blackboards.
  3. typing the implementation of a function into a text editor or directly into an interactive shell (this, of course, is also an activity performed by a person, or possibly a group of people, or possibly a very intelligent and dexterous cat, dog or monkey)

If you fear confusion with the above, you might be better served by phrases like “reading a function definition” and “processing the definition of a function”.

You say, “A function definition is a command.”  It’s not clear what a claim like that even means — it’s a matter of semantics — but, at the semantic level, it’s debatable.  Section 3.2 of the Bash manual (Shell Commands) lists six kinds of shell commands: Simple Commands, Pipelines, Lists, Compound Commands, Coprocesses, and GNU Parallel.  Function definitions don’t fit well into any of those categories.
</rant>

Chegando à sua pergunta e observando as sete etapas / operações,

  1. A leitura de entrada obviamente tem que acontecer antes que qualquer coisa mais possa acontecer. É, novamente, uma questão de semântica você poderia dizer que a entrada de leitura de um arquivo ou outra fonte de texto de fluxo faz parte de "ler uma definição de função" ou que é um pré-requisito / prelúdio para “Processando a definição de uma função”.
  2. Quebrando a entrada em palavras e operadores é claramente parte do “processamento da definição de uma função”.
    • Quebrar a entrada em tokens é, claro, um pré-requisito / prelúdio para analisar os tokens (passo 3, abaixo).
    • O manual diz "A expansão do alias é executada por esta etapa" e você mostra na pergunta que você sabe que expansão de alias ocorre quando a definição da função é lida.
  3. Analisando os tokens. Isso deve pelo menos começar durante a fase “processamento da definição de uma função” para o shell perceber que ele está olhando para uma definição de função e não um simples comando. Além disso, podemos fazer este experimento simples: digite um dos seguintes itens em um shell:

    myfunc1() {                     myfunc2() {
        <               or              ;
    }                               }
    

    Ele falhará com um "erro de sintaxe" antes de você ter a chance de digitar o } . ( > e & produzem o mesmo efeito.) Então, claramente, este passo faz parte do processamento da definição da função.

  1. Realizando as várias expansões de shell faz parte de chamar a função.
    • Você mostra na pergunta que você sabe que expansão de parâmetro não acontece quando a definição da função é lida.
    • É igualmente trivial demonstrar que a expansão do nome do caminho / nome do arquivo não acontece quando a definição da função é lida. No seu exemplo, altere echo $var (que deve ser echo "$var" , mas isso é outro assunto) para echo * .
      • Se você olhar para a definição da função, você verá que ainda diz echo * e não foi expandido.
      • Alterar diretório ( cd ) e / ou criar arquivo (s) e / ou excluir arquivo (s) e / ou renomear arquivo (s), e então chame (execute) a função. Você verá que ela exibe a lista atual de arquivos 1 no diretório atual, e não reflete o conteúdo do diretório onde / quando você definiu a função.
  2. A execução de redirecionamentos faz parte da chamada da função. Isso também é trivial para verificar. No seu exemplo, altere echo $var para echo hello > myfile .
    • Se você olhar para a definição da função, você verá que ainda diz  > myfile .
    • Verifique o diretório, e você verá que myfile não foi criado (ainda).
  3. Executando o comando - você realmente precisa perguntar?
  4. Aguardar a conclusão do comando não pode acontecer até que o comando tenha sido executado (passo 6), então isso, obviamente, é realizado apenas quando chamamos a função.

Em outras palavras, exatamente o que @ilkkachu disse .

O único caso especial excepcional em que posso pensar é que os passos 2 e 3 (análise lexical e análise) ocorrem (de novo) ao executar uma função se a função contiver eval declarações - mas acredito que isso esteja fora do escopo do que sua pergunta está realmente perguntando.

por 05.08.2017 / 23:35

Tags