Uma função em sh pode ter instruções zero?

3

Existem padrões relevantes que ditam o que uma implementação de sh deve fazer com uma função vazia?

O trecho a seguir define uma função com instruções zero

a() {
}

A versão subshell parece ser tratada de forma idêntica

a() (
)

ash e zsh aceitam a construção como uma função que não faz nada e tem um status de saída igual a zero.

ksh ( ksh93 ) e bash rejeitam essa função como um erro de sintaxe

$ a() {
> }
ksh: syntax error: '}' unexpected

e com bash

bash-4.4$ a() {
> }
bash: syntax error near unexpected token '}'
    
por Gregory Nisbet 07.03.2017 / 03:27

3 respostas

4

Não , uma função pode não ter um corpo vazio entre chaves em um aplicativo em conformidade.

POSIX define um comando de definição de função como:

fname ( ) compound-command [io-redirect ...]

onde todas essas palavras são espaços reservados para coisas definidas em outras partes da especificação. compound-command é o corpo da função.

Um comando composto é definido como um dos vários itens, incluindo loops, condicionais e declarações de caso, mas o mais relevante aqui é um agrupamento comando , que é definido em dois casos :

( compound-list )

Execute compound-list in a subshell environment; see Shell Execution Environment. Variable assignments and built-in commands that affect the environment shall not remain in effect after the list finishes. (... passage about arithmetic expansion elided ...)

{ compound-list ; }

Execute compound-list in the current process environment. The semicolon shown here is an example of a control operator delimiting the } reserved word. Other delimiters are possible, as shown in Shell Grammar; a <newline> is frequently used.

Um corpo {\n} vazio seria válido se compound-list pudesse estar vazio.

A Gramática do Shell , por sua vez, define as regras de análise da linguagem de comando do shell, incluindo compound_list :

compound_list    : linebreak term
                 | linebreak term separator

Isso significa que uma lista composta é linebreak seguida por term ou linebreak seguido por term e separator . separator é ; ou & . linebreak é uma sequência possivelmente vazia de novas linhas. Então, isso pode estar vazio se term puder estar vazio.

term é:

term             : term separator and_or
                 |                and_or

e and_or :

and_or           :                         pipeline
                 | and_or AND_IF linebreak pipeline
                 | and_or OR_IF  linebreak pipeline

As duas últimas linhas cobrem && e || . pipeline é uma sequência não vazia de command s separada por | caracteres. command é um comando simples, um comando composto ou uma definição de função. Portanto, term e command podem estar vazios se os comandos simples ou compostos puderem estar vazios.

Um comando simples sempre inclui um dos cmd_name , cmd_word ou cmd_prefix . cmd_prefix é um redirecionamento ou uma atribuição, opcionalmente anexado a outro prefixo. Os outros dois dividem-se em WORD , um token na gramática que é uma sequência não vazia de caracteres de palavras. Então, um comando simples nunca está vazio.

Já analisamos os comandos compostos, mas vamos voltar da perspectiva da gramática desta vez. Um comando composto é um dos grupos de chaves, subshell, for , while ou until loop e if ou case . Todas elas contêm uma palavra fixa (como " for ") ou ( ou { no mínimo. Então, um comando composto nunca está vazio.

Assim, um command nunca está vazio, portanto, pipeline nunca está vazio, nem and_or , term ou compound_list . Isso significa que

{
}

não é permitido e, portanto, a definição da função

a() {
}

também não é válido.

Todos os itens acima se aplicam a um script de shell portátil e em conformidade. zsh e ash estão livres para estender suas implementações para manipular scripts de outra forma inválidos da maneira que quiserem, e a implementação que eles escolheram parece sensata e conveniente. Bash, ksh, dash e outros tomaram a rota mais minimalista de implementar o que era necessário. Todas essas opções estão em conformidade.

Um script portátil sempre precisará fornecer um corpo de função não vazio, mas um script direcionado (digamos) zsh sozinho não.

    
por 07.03.2017 / 04:23
3

Parece que você está interessado na árvore de sintaxe para vários shells. Aqui está a seção relevante para o bash: link

As funções são definidas como [ 1 ]:

Functions are declared using this syntax:
name () compound-command [ redirections ]
or
function name [()] compound-command [ redirections ]

A parte em que você está interessado é a compound-command , que pode ser uma das seguintes [ 2 ]:

• Looping Constructs: Shell commands for iterative action.
• Conditional Constructs: Shell commands for conditional execution.
• Command Grouping: Ways to group commands.

A sintaxe {} e () é um command grouping , que pode ser um dos seguintes [ 3 ]:

( list )
{ list; }

Um list é definido como [ 4 ]:

A list is a sequence of one or more pipelines separated by one of the operators ‘;’, ‘&’, ‘&&’, or ‘||’, and optionally terminated by one of ‘;’, ‘&’, or a newline.

Um pipline é definido como [ 5 ]:

A pipeline is a sequence of one or more commands separated by one of the control operators ‘|’ or ‘|&’.

Seus exemplos de função contêm um comando composto, que deve conter um ou mais pipelines , cada um contendo um ou mais commands .

Portanto, no bash, você deve ter pelo menos um comando em sua função. Os outros shells provavelmente são semelhantes e têm seus guias de sintaxe prontamente disponíveis também.

Se por algum motivo você quiser ter uma função que não faz nada, você pode usar o espaço reservado de Bash embutido, que é : - não faz nada com sucesso.

a(){:}
    
por 07.03.2017 / 03:58
-1

Este é o mais próximo de esvaziar o que o bash recebe:

a (){  
  :   
}
    
por 07.03.2017 / 03:51