No trabalho, escrevo scripts bash com freqüência. Meu supervisor sugeriu que todo o script seja dividido em funções, semelhante ao seguinte exemplo:
#!/bin/bash # Configure variables declare_variables() { noun=geese count=three } # Announce something i_am_foo() { echo "I am foo" sleep 0.5 echo "hear me roar!" } # Tell a joke walk_into_bar() { echo "So these ${count} ${noun} walk into a bar..." } # Emulate a pendulum clock for a bit do_baz() { for i in {1..6}; do expr $i % 2 >/dev/null && echo "tick" || echo "tock" sleep 1 done } # Establish run order main() { declare_variables i_am_foo walk_into_bar do_baz } main
Existe algum motivo para fazer isso além de “legibilidade” , que acho que poderia ser igualmente bem estabelecido com mais alguns comentários e espaçamento entre linhas?
Isso faz com que o script seja executado com mais eficiência (eu esperaria o contrário, se houver) ou é mais fácil modificar o código além do potencial de legibilidade mencionado anteriormente? Ou é realmente apenas uma preferência estilística?
Observe que embora o script não o demonstre bem, a “ordem de execução” das funções em nossos scripts reais tende a ser muito linear – walk_into_bar
depende de coisas que i_am_foo
fez e do_baz
age em coisas criadas por walk_into_bar
– portanto, ser capaz de trocar arbitrariamente a ordem de execução não é algo que geralmente estaríamos fazendo. Por exemplo, você não iria querer colocar de repente declare_variables
após walk_into_bar
, isso quebraria as coisas.
Um exemplo de como eu escreveria o script acima seria:
#!/bin/bash # Configure variables noun=geese count=three # Announce something echo "I am foo" sleep 0.5 echo "hear me roar!" # Tell a joke echo "So these ${count} ${noun} walk into a bar..." # Emulate a pendulum clock for a bit for i in {1..6}; do expr $i % 2 >/dev/null && echo "tick" || echo "tock" sleep 1 done
Comentários
Resposta
Comecei a usar o mesmo estilo de programação bash após ler a postagem do blog de Kfir Lavi “Programação Bash defensiva” . Ele fornece alguns bons motivos, mas pessoalmente acho estes os mais importantes:
-
os procedimentos tornam-se descritivos: é muito mais fácil descobrir o que uma parte específica do código deve para fazer. Em vez de uma parede de código, você vê “Oh, a função
find_log_errors
lê esse arquivo de log em busca de erros”. Compare com encontrar um monte de linhas awk / grep / sed que use deus sabe que tipo de regex no meio de um script extenso – você não tem ideia do que ele está fazendo lá, a menos que haja comentários. -
você pode depurar funções incluindo
set -x
eset +x
. Depois de saber que o resto do código funciona bem, você pode usar este truque para focar na depuração apenas daquela função específica. Claro, você pode incluir partes do script, mas e se for uma parte longa? É mais fácil fazer algo assim:set -x parse_process_list set +x
-
uso de impressão com
cat <<- EOF . . . EOF
. Eu usei isso algumas vezes para tornar meu código muito mais profissional. Além disso,parse_args()
com a funçãogetopts
é bastante conveniente. Novamente, isso ajuda na legibilidade, em vez de colocar tudo no script como uma parede gigante de texto. Também é conveniente reutilizá-los.
E, obviamente, isso é muito mais legível para alguém que conhece C, Java ou Vala, mas tem experiência limitada em bash. No que diz respeito à eficiência, não há muito o que você possa fazer – o bash em si não é a linguagem mais eficiente e as pessoas preferem perl e python quando se trata de velocidade e eficiência.No entanto, você pode nice
uma função:
nice -10 resource_hungry_function
Comparado a chamar nice em cada linha de código, isso diminui muito a digitação E pode ser convenientemente usado quando você deseja que apenas uma parte do seu script seja executada com prioridade mais baixa.
Executar funções em segundo plano, na minha opinião, também ajuda quando você deseja que o todo monte de instruções para executar em segundo plano.
Alguns dos exemplos em que usei este estilo:
- https://askubuntu.com/a/758339/295286
- https://askubuntu.com/a/788654/295286
- https://github.com/SergKolo/sergrep/blob/master/chgreeterbg.sh
Comentários
- Não tenho certeza se você deve levar muito a sério qualquer sugestão desse artigo. É verdade que tem algumas boas ideias, mas claramente não é alguém acostumado a scripts de shell. Não é um variável única em qualquer um dos exemplos está entre aspas (!) e sugere o uso de UPPER C Nomes de variáveis ASE, o que geralmente é uma idéia muito ruim, pois podem entrar em conflito com as variáveis env existentes. Seus pontos nesta resposta fazem sentido, mas o artigo com link parece ter sido escrito por alguém que está acostumado com outras línguas e está tentando forçar seu estilo para o bash.
- @terdon, voltei ao artigo e reli. O único lugar onde o autor menciona a nomenclatura de variáveis em maiúsculas é em ” Variáveis globais imutáveis “. Se você considerar variáveis globais como aquelas que devem estar dentro do ambiente da função ‘, então faz sentido torná-las capitais. Na observação lateral, bash ‘ s manual não ‘ t convenção de estado para o caso de variável. Mesmo aqui a resposta aceita diz ” geralmente ” e a única ” standard ” é do Google, que não ‘ t representa toda a indústria de TI.
- @terdon em outra nota, concordo 100% que a citação de variável deveria ter sido mencionada no artigo, e foi apontada nos comentários do blog também. Além disso, eu não ‘ julgaria alguém que usa esse estilo de codificação, independentemente de eles ‘ serem usados em outro idioma ou não. Toda esta pergunta e respostas mostram claramente as ‘ vantagens para ela e a pessoa ‘ grau em que ‘ reutilizado em outro idioma é provavelmente irrelevante aqui.
- @terdon bem, o artigo foi postado como parte da ” fonte ” material. Eu poderia ter postado tudo como minha opinião, mas só tive que dar crédito a algumas coisas que aprendi com o artigo e que tudo isso veio de pesquisas ao longo do tempo. O autor ‘ página do LinkedIn mostra que tem boa experiência com Linux e TI em geral, então eu ‘ acho que o artigo não ‘ não mostro isso, mas confio na sua experiência quando se trata de Linux e script de shell, então você pode estar certo.
- Isso ‘ é uma resposta excelente, mas eu ‘ d também gostaria de adicionar que o escopo variável no Bash é funky. Por esse motivo, prefiro declarar minhas variáveis dentro de funções usando
local
e chamando tudo por meio da funçãomain()
. Isso torna as coisas muito mais gerenciáveis e você pode evitar uma situação potencialmente confusa.
Resposta
Legibilidade é uma coisa. Mas há mais na modularização do que apenas isso. ( Semimodularização talvez seja mais correta para funções.)
Em funções, você pode manter algumas variáveis locais, o que aumenta a confiabilidade , diminuindo a chance de as coisas estão ficando bagunçadas.
Outro profissional das funções é a reutilização . Depois que uma função é codificada, ela pode ser aplicada várias vezes no script. Você também pode portá-lo para outro script.
Seu código agora pode ser linear, mas no futuro você pode entrar no domínio de multi-threading ou multi- processamento no mundo Bash. Depois de aprender a fazer coisas em funções, você estará bem equipado para a etapa em paralelo.
Mais um ponto a acrescentar. Como a Etsitpab Nioliv observa no comentário abaixo, é fácil redirecionar de funções como uma entidade coerente. Mas há mais um aspecto de redirecionamentos com funções. Ou seja, os redirecionamentos podem ser definidos ao longo da definição da função. Ex .:
f () { echo something; } > log
Agora, nenhum redirecionamento explícito é necessário para as chamadas de função.
$ f
Isso pode poupar muitas repetições, o que novamente aumenta a confiabilidade e ajuda a manter as coisas em ordem.
Veja também
Comentários
- Muito bom embora fosse muito melhor se fosse dividido em funções.
- Talvez adicionar essas funções permitem que você importe esse script para outro script (usando
source
ou. scriptname.sh
e use essas funções como se estivessem no seu novo script. - Isso ‘ já foi abordado em outra resposta.
- Agradeço isso. Mas ‘ prefiro deixar que outras pessoas também sejam importantes.
- Enfrentei um caso hoje onde eu tive que redirecionar parte da saída de um script para um arquivo (para enviá-lo por e-mail) em vez de ecoar. Eu simplesmente tive que fazer myFunction > > myFile para redirecionar a saída das funções desejadas. Bastante conveniente. Pode ser relevante.
Resposta
Em meu comentário, mencionei três vantagens das funções:
-
Elas são mais fáceis de testar e verificar a exatidão.
-
As funções podem ser facilmente reutilizadas (originadas) em scripts futuros
-
Seu chefe gosta deles.
E nunca subestime a importância do número 3.
Eu gostaria de abordar mais um problema:
… então, poder trocar arbitrariamente a ordem de execução não é algo que geralmente estaríamos fazendo. Por exemplo, você não iria querer colocar de repente
declare_variables
apóswalk_into_bar
, isso quebraria as coisas.
Para obter o benefício de dividir o código em funções, deve-se tentar tornar as funções o mais independentes possível. Se walk_into_bar
exigir uma variável que não é usado em outro lugar, então essa variável deve ser definida e tornada local para walk_into_bar
. O processo de separar o código em funções e minimizar suas interdependências deve tornar o código mais claro e simples .
O ideal é que as funções sejam fáceis de testar individualmente. Se, por causa das interações, elas não forem fáceis de testar, isso é um sinal de que podem se beneficiar da refatoração.
Comentários
- Eu ‘ d argumento que ‘ às vezes é sensível para modelar e impor essas dependências, em vez de refatorar para evitá-las (já que se houver h deles, e eles ‘ são suficientemente cabeludos, o que pode levar a um caso em que as coisas não são mais modularizadas em funções). Um caso de uso muito complicado inspirou uma estrutura para fazer exatamente isso .
- O que deve ser dividido em funções deve ser, exceto o exemplo leva isso longe demais. Acho que o único que realmente me incomoda é a função de declaração de variável. Variáveis globais, especialmente as estáticas, devem ser definidas globalmente em uma seção comentada dedicada a esse propósito. As variáveis dinâmicas devem ser locais para as funções que as usam e modificam.
- @Xalorous I ‘ vi uma prática em que variáveis globais são inicializadas em um procedimento, como uma etapa intermediária e rápida antes do desenvolvimento de um procedimento que lê seu valor de um arquivo externo … Concordo que deve ser mais limpo separar definição e inicialização, mas raramente você tem que se dobrar para passar pelo vantagem número 3
;-)
Resposta
Embora eu concorde totalmente com a capacidade de reutilização , legibilidade e delicadamente beijando os chefes, mas há uma outra vantagem das funções em bash : escopo de variável . Como LDP mostra :
#!/bin/bash # ex62.sh: Global and local variables inside a function. func () { local loc_var=23 # Declared as local variable. echo # Uses the "local" builtin. echo "\"loc_var\" in function = $loc_var" global_var=999 # Not declared as local. # Therefore, defaults to global. echo "\"global_var\" in function = $global_var" } func # Now, to see if local variable "loc_var" exists outside the function. echo echo "\"loc_var\" outside function = $loc_var" # $loc_var outside function = # No, $loc_var not visible globally. echo "\"global_var\" outside function = $global_var" # $global_var outside function = 999 # $global_var is visible globally. echo exit 0 # In contrast to C, a Bash variable declared inside a function #+ is local ONLY if declared as such.
Não vejo isso com muita frequência no mundo real scripts de shell, mas parece uma boa ideia para scripts mais complexos. Reduzir a coesão ajuda a evitar bugs em que você “reponha uma variável esperada em outra parte do código .
Reutilização geralmente significa criar uma biblioteca comum de funções e source
inserir essa biblioteca em todos os seus scripts. Isso não ajudará a executá-los mais rapidamente, mas ajudará você a escrevê-los mais rápido.
Comentários
- Poucas pessoas estão usando explicitamente
local
, mas acho que a maioria das pessoas que escrevem scripts divididos em funções ainda segue o princípio de design. Usignlocal
apenas torna mais difícil introduzir bugs. -
local
torna as variáveis disponíveis para a função e seus filhos, por isso ‘ é realmente bom ter uma variável que pode ser passada abaixo da função A, mas indisponível para a função B, que pode querer ter uma variável com o mesmo nome, mas com finalidades diferentes.Para que ‘ seja bom para definir o escopo, e como Voo disse – menos bugs
Resposta
Você divide o código em funções pelo mesmo motivo que faria para C / C ++, python, perl, ruby ou qualquer outro código de linguagem de programação. A razão mais profunda é a abstração – você encapsula tarefas de nível inferior em primitivas (funções) de nível superior para que não precise se preocupar com como as coisas são feitas. Ao mesmo tempo, o código se torna mais legível (e sustentável), e o a lógica do programa se torna mais clara.
No entanto, olhando para o seu código, acho bastante estranho ter uma função para declarar variáveis; isso realmente me faz erguer uma sobrancelha.
Comentários
- Resposta subestimada IMHO. Você sugere declarar as variáveis na
main
função / método, então?
Resposta
Um motivo completamente diferente daqueles já dados em outras respostas: um motivo pelo qual esta técnica é às vezes usada, onde o único declaração de não-definição de função no nível superior é uma chamada para main
, é para garantir que o script não faça acidentalmente nada desagradável se o script for truncado. O script pode estar truncado se for canalizado do processo A para o processo B (o shell), e o processo A termina por qualquer motivo antes de terminar de escrever todo o script. É mais provável que isso aconteça se o processo A buscar o script de um recurso remoto. Embora por motivos de segurança não seja uma boa ideia, é algo que é feito e alguns scripts foram modificados para antecipar o problema.
Comentários
- Interessante! Mas acho preocupante que seja preciso cuidar dessas coisas em cada um dos programas. Por outro lado, exatamente esse
main()
padrão é comum em Python, onde se usaif __name__ == '__main__': main()
no final do arquivo. - O idioma python tem a vantagem de permitir que outros scripts
import
o script atual sem executarmain
. Suponho que um guarda semelhante poderia ser colocado em um script bash. - @Jake Cobb Sim. Agora faço isso em todos os novos scripts bash. Eu tenho um script que contém uma infraestrutura central de funções usadas por todos os novos scripts. Esse script pode ser obtido ou executado. Se originado, sua função principal não é executada. A detecção de origem versus execução ocorre pelo fato de que o BASH_SOURCE contém o nome do script em execução. Se ‘ for igual ao script principal, o script está sendo executado. Caso contrário, ele ‘ está sendo originado.
- Intimamente relacionado a esta resposta, o bash usa processamento baseado em linha simples quando executado a partir de um arquivo já no disco. Se o arquivo mudar enquanto o script está sendo executado, o contador de linha não ‘ muda e ‘ continuará na linha errada. Encapsular tudo em funções garante que ‘ seja carregado na memória antes de executar qualquer coisa, portanto, alterar o arquivo não ‘ o afeta.
Resposta
Alguns truísmos relevantes sobre programação:
- Seu programa mudará, mesmo se seu chefe insistir que não é o caso.
- Apenas o código e a entrada afetam o comportamento do programa.
- Nomear é difícil.
Os comentários começam como um paliativo para não ser capaz de expressar suas idéias claramente em código * e piorar (ou simplesmente errar) com a mudança. Portanto, se for possível, expresse conceitos, estruturas, raciocínio, semântica, fluxo, tratamento de erros e tudo o mais pertinente à compreensão do código como código.
Dito isso, As funções do Bash têm alguns problemas não encontrados na maioria das linguagens:
- O namespacing é terrível no Bash. Por exemplo, esquecer de usar a palavra-chave
local
resulta em poluir o namespace global. - Usar
local foo="$(bar)"
resulta em perder o código de saída debar
. - Não há parâmetros nomeados, então você deve ter em mente o que
"$@"
significa em diferentes contextos.
* Lamento se isso ofende, mas depois usando comentários por alguns anos e desenvolvendo sem eles ** por mais anos é bastante claro qual é superior.
** Usar comentários para licenciamento, documentação de API e similares ainda é necessário.
Comentários
- Eu defino quase todas as variáveis locais, declarando-as como nulas no início da função …
local foo=""
Em seguida, configurando-os usando a execução do comando para agir no resultado …foo="$(bar)" || { echo "bar() failed"; return 1; }
. Isso nos tira da função rapidamente quando um valor obrigatório não pode ser definido. As chaves são necessárias para garantir quereturn 1
seja executado apenas em caso de falha. - Só queria comentar sobre seus marcadores. Se você usar ‘ funções de subshell ‘ (funções delimitadas por parênteses e não colchetes), você 1) don ‘ não precisa usar o local, mas obtenha os benefícios do local, 2) Não ‘ não tenha o problema de perder o código de saída da substituição do comando em
local foo=$(bar)
tanto (porque você ‘ não está usando local) 3) Não ‘ não precisa se preocupar sobre poluir ou alterar acidentalmente o escopo global 4) são capazes de transmitir ‘ parâmetros nomeados ‘ que são ‘ local ‘ para sua função usando a sintaxefoo=bar baz=buz my-command
Resposta
Um processo requer uma sequência. A maioria das tarefas é sequencial. Não faz sentido mexer com o pedido.
Mas a grande novidade da programação – que inclui scripts – são os testes. Testando, testando, testando. Quais scripts de teste você tem atualmente para validar a exatidão de seus scripts?
Seu chefe está tentando orientá-lo de ser um script kiddy a um programador. Esta é uma boa direção a seguir. As pessoas que vierem atrás de você gostarão de você.
MAS. Lembre-se sempre de suas raízes orientadas para o processo. Se fizer sentido ordenar as funções na sequência em que são normalmente executadas, faça-o, pelo menos como uma primeira passagem.
Mais tarde, você verá que algumas de suas funções são manipulando entradas, outras saídas, outros processando, outros modelando dados e outros manipulando os dados, então pode ser inteligente agrupar métodos semelhantes, talvez até movendo-os para arquivos separados.
Ainda mais tarde, você pode percebi que agora você escreveu bibliotecas de pequenas funções auxiliares que usa em muitos de seus scripts.
Resposta
Comentários e o espaçamento não pode chegar perto da legibilidade que as funções podem, como irei demonstrar. Sem funções, você não pode ver a floresta por causa das árvores – grandes problemas se escondem entre muitas linhas de detalhes. Em outras palavras, as pessoas não podem focar simultaneamente nos pequenos detalhes e no quadro geral. Isso pode não ser óbvio em um script curto; desde que permaneça curto, pode ser legível o suficiente. O software fica maior, mas não menor , e certamente faz parte de todo o sistema de software da sua empresa, que é certamente muito maior, provavelmente milhões de linhas.
Considere se eu lhe dei instruções como estas:
Place your hands on your desk. Tense your arm muscles. Extend your knee and hip joints. Relax your arms. Move your arms backwards. Move your left leg backwards. Move your right leg backwards. (continue for 10,000 more lines)
Ao chegar na metade, ou mesmo 5%, você já deve ter esquecido quais foram as primeiras etapas. Você não poderia localizar a maioria dos problemas, porque você não conseguia ver a floresta por causa das árvores. Compare com as funções:
stand_up(); walk_to(break_room); pour(coffee); walk_to(office);
Isso é certamente muito mais compreensível, não importa quantos comentários você possa colocar na versão sequencial linha por linha. também torna muito mais provável que você “note que se esqueceu de preparar o café, e provavelmente esqueci sit_down () no final. Quando sua mente está pensando nos detalhes de regexes grep e awk, você “não pode estar pensando em uma imagem ampla -” e se não houver café feito “?
As funções permitem principalmente que você tenha uma visão geral, e observe que você se esqueceu de fazer o café (ou que alguém pode preferir chá). Em outro momento, em um estado de espírito diferente, você se preocupa com a implementação detalhada.
Existem também outros benefícios discutidos em outras respostas, é claro. Outro benefício não claramente declarado nas outras respostas é que as funções fornecem uma garantia importante na prevenção e correção de bugs. Se você descobrir que alguma variável $ foo na função apropriada walk_to () estava errada, você sabe que só precisa olhar as outras 6 linhas dessa função para encontrar tudo que poderia ter sido afetado por aquele problema, e tudo que poderia fizeram com que fosse errado. Sem funções (adequadas), qualquer coisa em todo o sistema pode ser a causa de $ foo estar incorreto, e qualquer coisa e tudo pode ser afetado por $ foo. Portanto, você não pode consertar $ foo com segurança sem examinar novamente cada linha do programa. Se $ foo for local para uma função, você pode garantir que todas as alterações são seguras e corretas marcando apenas essa função.
Comentários
- Esta isn ‘ t
bash
sintaxe.No entanto, ‘ é uma pena; Eu não ‘ não acho que haja uma maneira de passar a entrada para funções como essa. (ou seja,pour();
<coffee
). Parece mais comc++
ouphp
(eu acho). - @ tjt263 sem os parênteses, é ‘ S sintaxe bash: sirva café. Com parênteses, é ‘ praticamente qualquer outro idioma. 🙂
Resposta
Tempo é dinheiro
Existem outras boas respostas que revelam as razões técnicas para escrever modularmente um script, potencialmente longo, desenvolvido em um ambiente de trabalho, desenvolvido para ser usado por um grupo de pessoas e não apenas para seu próprio uso.
Eu quero foque em uma expectativa: em um ambiente de trabalho “tempo é dinheiro” . Portanto, a ausência de bugs e o desempenho de seu código são avaliados junto com legibilidade , testabilidade, manutenção, refatoração, capacidade de reutilização …
Escrita em ” módulos “ um código diminuirá o tempo de leitura necessário não apenas pelo codificador em si, mas até mesmo o tempo usado pelos testadores ou pelos o chefe. Além disso, observe que o tempo de um chefe geralmente é pago mais do que o tempo de um codificador e seu chefe avaliará a qualidade do seu trabalho.
Além disso, escrevendo em independente “modules” um código (até mesmo um script bash) permitirá que você trabalhe em “paralelo” com outro componente de sua equipe encurtando o tempo geral de produção e usando, na melhor das hipóteses, a experiência individual, para revisar ou reescrever uma parte sem nenhum efeito colateral sobre as outras, para reciclar o código que você acabou de escrever “como está” para outro programa / script, para criar bibliotecas (ou bibliotecas de snippets), para reduzir o tamanho geral e a probabilidade de erros relacionados, para depurar e testar cada parte individual … e é claro que irá organizar de forma lógica seção seu programa / script e melhorar sua legibilidade. Todas as coisas que irão economizar tempo e dinheiro. A desvantagem é que você tem que seguir os padrões e comentar suas funções (que você não tem menos a fazer em um ambiente de trabalho).
Seguir um padrão tornará seu trabalho mais lento no início, mas irá acelerar o trabalho de todos os outros (e do seu também) depois. Na verdade, quando a colaboração aumenta em número de pessoas envolvidas, isso se torna uma necessidade inevitável. Assim, por exemplo, mesmo que eu acredite que as variáveis globais devam ser definidas globalmente e não em uma função, posso entender um padrão que as inicializa em uma função chamada declare_variables()
chamado sempre na primeira linha do main()
um …
Por último, mas não menos importante, não subestime a possibilidade no código-fonte moderno editores para mostrar ou ocultar rotinas seletivamente separadas ( Dobramento de código ). Isso manterá o código compacto e focalizará o usuário salvando novamente.
Aqui acima você pode ver como é desdobrado apenas a função walk_into_bar()
. Mesmo se os outros tivessem 1000 linhas cada, você ainda poderia manter sob controle todo o código em uma única página. Observe que está dobrado até mesmo na seção onde você declara / inicializa as variáveis.
Resposta
Outro motivo que é freqüentemente esquecido é a análise sintática do bash:
set -eu echo "this shouldn"t run" { echo "this shouldn"t run either"
Este script obviamente contém um erro de sintaxe e o bash não deveria executá-lo, certo? Errado.
~ $ bash t1.sh this shouldn"t run t1.sh: line 7: syntax error: unexpected end of file
Se agrupássemos o código em uma função, isso não aconteceria:
set -eu main() { echo "this shouldn"t run" { echo "this shouldn"t run either" } main
~ $ bash t1.sh t1.sh: line 10: syntax error: unexpected end of file
Resposta
Além das razões dadas em outras respostas:
- Psicologia: Um programador cuja produtividade está sendo medida em linhas de código terá um incentivo para escrever código desnecessariamente prolixo. Quanto mais gerenciamento é concentrando-se nas linhas de código, mais incentivo o programador tem para expandir seu código com complexidade desnecessária.Isso é indesejável, uma vez que o aumento da complexidade pode levar ao aumento do custo de manutenção e do esforço necessário para correção de erros.
Comentários
- Não é uma resposta tão ruim, como dizem os votos negativos. Nota: agc diz, também esta é uma possibilidade, e sim, é. Ele não ‘ diz que seria a única possibilidade e não ‘ acusa ninguém, apenas declara os fatos. Embora eu ache que hoje quase não se ouve uma linha de código ” – > ” $$ ” trabalho de contrato de estilo, em meios indiretos, é bastante comum, que sim, a massa do código produzido conta pelos líderes / bosses.
main()
no topo e adicionomain "$@"
na parte inferior para chamá-lo. Isso permite que você veja o alto nivelar a lógica do script ao abri-lo.local
– fornece escopo variável, o que é extremamente importante em qualquer script não trivial.