Se você estiver preocupado apenas com a contagem de linhas do seu arquivo, poderá fazer algo assim:
my_func () {
echo "Hello, world"
} && my_func
Eu uso o Ubuntu 16.04 com o Bash e tenho um arquivo com 10 funções. Cada função faz essencialmente uma tarefa diferente. No final de cada função, eu chamo assim:
x() {
echo
}
x
As chamadas adicionam mais 10 linhas ao arquivo, linhas que eu gostaria de salvar do arquivo por razões estéticas, porque eu executo todas as funções naquele arquivo (na ordem em que elas já estão classificadas).
Naturalmente, apenas o fornecimento (execução na sessão atual) ou bashing (execução em uma subsessão) não é suficiente (com prazer, porque às vezes se deseja source
/ bash
sem executar todas as funções ).
A solução que eu preferiria para esse problema estético menor seria chamar todas as funções, de alguma forma, diretamente da linha de comando, logo após o sourcing / bashing do arquivo.
É possível no Bash?
Você pode usar:
source <(declare -f | grep -o '^[[:alnum:]]\+')
Isso lista todas as definições de função no escopo ( declare -f
) Em seguida, filtra apenas seus nomes, que serão as únicas cadeias alfanuméricas na margem esquerda ( grep -o '^[[:alnum:]]\+'
) e, finalmente, obtém a saída resultante, que é uma lista por linha de nomes de funções, por meio de processo de substituição para que todos sejam chamados no shell atual.
Os itens acima funcionam com GNU ou BSD grep
s que possuem -o
, mas você pode trocar um comando sed
ou awk
adequado se necessário.
As funções não estarão em nenhuma ordem particular aqui (a ordem de tabela de hash do Bash, eu acho, que é essencialmente aleatória). Se você precisar preservar um pedido, nomeie-o adequadamente e adicione um sort
no meio:
source <(declare -f | grep -o '^[[:alnum:]]\+'|sort)
Se as funções em si são destinadas a serem chamadas independentemente, essa estrutura de nomes pode ser indesejável. Eu não vejo uma maneira simples de contornar isso.
Isso funciona dentro de um único arquivo. Se você estiver fazendo o sourcing do arquivo em um shell que já tem funções definidas nele, é necessário lembrar quais já existem e ignorá-los:
funcs=($(declare -f | grep -o '^[[:alnum:]]\+'|sort))
source file
source <(declare -f | grep -o '^[[:alnum:]]\+' | sort - <(printf '%s\n' "${funcs[@]}" | uniq -u)
Existem várias maneiras de fazer isso, todas as quais são bastante estranhas. Isso também cai quando você redefine uma função existente. Outra abordagem seria grep
out todas as linhas de definição de função do próprio arquivo; se você está estruturado sobre como você escreve, isso funciona também.
Uma abordagem possivelmente melhor, se você controlar o conteúdo do arquivo, seria listar os nomes das funções, na ordem que você deseja que sejam chamados, em uma definição de matriz de linha única na parte inferior do arquivo. Então você pode passar por ele na shell de sourcing e fazer o que você precisa.
Esta abordagem seria mais clara e menos frágil. No entanto, introduz a possibilidade de os dois locais ficarem fora de sincronia.
Se você realmente quer um one-liner, eu criei isto, assumindo um arquivo scripts/1.sh
:
shopt -s extdebug; source scripts/1.sh; source="$_"; while IFS= read -r func; do declare_output="$(declare -F "${func##* }")"; [[ ${declare_output##* } == $source ]] && "${func##* }"; done < <(declare -F)
Basicamente, isso usa declare
para determinar quais funções em seu ambiente vieram do arquivo originado e as executam. Eu tenho três funções em scripts/1.sh
, que echo Goodbye
, cruel
e world.
, e minha saída desse comando é:
Goodbye,
cruel
world.
Eu não sei se a ordem da saída declare
é garantida como a ordem em que as funções foram originadas, então você pode ter que nomear as funções apropriadamente e usar sort
.
Eu sugiro manter as chamadas explícitas, por vários motivos. Eles permitem que você remova temporariamente algumas funções da lista de chamadas, altere a ordem, mantenha versões antigas das funções durante a edição e tenha funções de utilidade que são chamadas apenas de outras funções (mas não do nível "principal"). O último em particular parece importante para a adequada estruturação do programa.
Mas se você realmente quiser, você pode fazer isso. Embora eu possa sugerir, pelo menos, adicionar algum tipo de designador para as funções autorunnable. Parcialmente baseado no comentário de @ cas, este executa todas as funções marcadas com # AUTORUN
na linha acima.
#!/bin/bash
foo() { echo foo; }
# AUTORUN
bar() { echo bar; }
while IFS= read -r f; do
$f
done < <(sed -nE '/^# *AUTORUN/!d; n; s/^([a-zA-Z0-9_]+) *\(\).*//p' "${BASH_SOURCE[0]}")
Provavelmente precisa do GNU sed no formulário atual.
Tags bash shell-script function