atribuir e inspecionar metadados da função bash

10

Costumo gerar e registrar muitas funções bash que automatizam muitas das tarefas que normalmente faço nos meus projetos de desenvolvimento. Essa geração depende dos metadados do projeto em que estou trabalhando.

Quero anotar as funções com as informações do projeto que foram geradas, desta maneira:

func1() {
# This function was generated for project: PROJECT1
echo "do my automation"
}

Idealmente, eu seria capaz de ver o comentário ao inspecionar a definição:

$ type func1

func1 is a function
func1 () 
{
    # This function was generated for project: PROJECT1
    echo "do my automation"
}

Mas, de alguma forma, o bash parece ignorar os comentários no momento do carregamento da função, não ao executá-la. Então os comentários são perdidos e eu recebo este resultado:

func1 is a function
func1 () 
{
    echo "do my automation"
}

Existe alguma maneira de atribuir metadados a funções e verificá-los depois? É possível recuperá-lo ao inspecionar a definição com o tipo?

yucer
fonte
1
Não é uma solução (daí o comentário), mas a solução alternativa que eu uso é verificar se $1existe -he, em seguida, printf/ echouma ajuda / uso em uma linha / qualquer que seja.
John N
2
Veja também: unix.stackexchange.com/questions/295022/…
Jeff Schaller

Respostas:

13
function func_name()
{
  : '
  Invocation:   func_name $1 $2 ... $n
  Function:     Display the values of the supplied arguments, in double quotes.
  Exit status:  func_name always returns with exit status 0.
  ' :
  local i
  echo "func_name: $# arguments"
  for ((i = 1; i <= $#; ++i)); do
    echo "func_name [$i] \"$1\""
    shift
  done
  return 0
}
AlexP
fonte
2
hmmm, docstrings no bash. Quem sabia?
Brian Minton 9/16
Existe alguma maneira de consultar esse comentário? Eu pensando em uma função de ajuda genery para todos os comandos.
yucer
7

Sim, typeparece imprimir apenas as partes de uma função que será executada. Isso me parece razoável, na verdade, já que geralmente é tudo o que você está interessado ao consultar type.

Como solução alternativa, em vez de usar comentários, adicione seus metadados como este:

func1() {
    meta="This function was generated for project: PROJECT1"
    echo "do my automation"
}

Não há necessidade de realmente usar essa variável, mas ela aparecerá ao consultar a função com type:

$ type func1
func1 is a function
func1 () 
{ 
    meta="This function was generated for project: PROJECT1";
    echo "do my automation"
}
terdon
fonte
2
Se você quiser evitar o armazenamento de uma variável, você pode usar o operador nop ":" desta forma: função func () {: # "metadados" fazer o seu}
Luchostein
1
Eu acho que aspas simples são melhores do que aspas duplas aqui, apenas no caso de haver expansões indesejadas ocultas na doutrina
Digital Trauma
6

Você pode usar o nop embutido :. Além disso, você não precisa armazená-lo como uma variável:

function f() {
  : your metadata here
  : "or here"
  # do yours
}

EDIT : Cuidado com caracteres especiais em seus metadados. Para texto puro, você pode usar:

: <<EOT
Your metadata text here.
EOT

EDIT : você pode usar uma matriz associativa global para armazenar todos os metadados da função:

declare -A METADATA=()
METADATA[fun1]='foo bar'
function fun1() {
  echo I have some metadata: "${METADATA[$FUNCNAME]}"
}
METADATA[fun2]='baz you'
function fun2() {
  echo I have some other metadata: "${METADATA[$FUNCNAME]}"
}

Dessa forma, você não precisa analisar a saída declareou typea saída, mas apenas consultar a chave de uma matriz.

Luchostein
fonte
1
Tenha cuidado - your metadata herepode conter expansões com efeitos colaterais. Melhor usar aspas simples como a resposta de @ AlexP.
Digital Trauma
Sim, mas você também deve ter cuidado entre aspas.
Luchostein
3

Você consegue fazer isso.

$ f() { This function does nothing. 2> /dev/null; }
$ f
$ type f
f is a function
f () 
{ 
    This function does nothing. 2> /dev/null
}

fonte
mas a função ainda deve fazer suas coisas depois de ser anotada. Na amostra que eu incluí, o eco ainda deve funcionar quando eu chamo a função normalmente.
yucer
@yucer Seria. Isto é apenas uma ilustração. Tente. Mas tem suas limitações. Nenhum caractere especial como (pode ser usado e a primeira palavra não deve ser um comando válido.
Está bem. Ele acha que é uma resposta válida, embora demore um tempo extra para ser executado. Também pode ser melhor incluir o eco e os metadados que eu usei no meu exemplo.
yucer