Por que escrever um script bash inteiro em funções?

59

No trabalho, escrevo scripts bash com frequência. Meu supervisor sugeriu que o script inteiro fosse 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 alguma razão para fazer isso além da "legibilidade", que eu acho que poderia estar igualmente bem estabelecida com mais alguns comentários e espaçamento entre linhas?

Isso faz com que o script seja executado com mais eficiência (eu realmente esperaria o oposto, se houver) ou facilita a modificação do código além do potencial de legibilidade acima mencionado? 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_bardepende do que i_am_foofoi feito e do_bazatua no que foi configurado walk_into_bar- A capacidade de trocar arbitrariamente a ordem de execução não é algo que geralmente estaríamos fazendo. Por exemplo, você não iria de repente querem colocar declare_variablesdepois walk_into_bar, que iria quebrar 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
Doktor J
fonte
30
Eu gosto do seu chefe. Nos meus scripts, eu também coloco main()na parte superior e adiciono main "$@"na parte inferior para chamá-lo. Isso permite que você veja a lógica do script de alto nível quando você a abre.
John Kugelman apoia Monica
22
Eu discordo da noção de que a legibilidade pode "ser igualmente bem estabelecida com mais alguns comentários e espaçamento entre linhas". Exceto talvez para a ficção, eu não gostaria de lidar com um livro que não possui um índice e nomes descritivos para cada capítulo e seção. Nas linguagens de programação, esse é o tipo de legibilidade que as funções podem fornecer e os comentários não.
Rhymoid
6
Observe que as variáveis ​​declaradas nas funções devem ser declaradas local- isso fornece um escopo variável que é incrivelmente importante em qualquer script não trivial.
Boris the Spider
8
Eu discordo do seu chefe. Se você precisar dividir seu script em funções, provavelmente não deve escrever um script de shell em primeiro lugar. Escreva um programa em seu lugar.
el.pescado
6
As funções são para processos repetidos, dentro do script ou em mais de um script. Eles também permitem que metodologias uniformes sejam implementadas. Por exemplo, usando uma função para gravar no syslog. Desde que todos usem a mesma função, suas entradas de syslog são mais consistentes. Funções de uso único, como o seu exemplo, desnecessariamente complicam o script. Em alguns casos, eles introduzem problemas (escopo variável).
Xalorous 30/09/16

Respostas:

40

Comecei a usar esse mesmo estilo de programação bash depois de ler a postagem no blog de Kfir Lavi, "Defensive Bash Programming" . Ele dá algumas boas razões, mas pessoalmente acho essas as mais importantes:

  • Os procedimentos se tornam descritivos: é muito mais fácil descobrir o que uma parte específica do código deve fazer. Em vez de código de parede, você vê "Oh, a find_log_errorsfunção lê esse arquivo de log para erros". Compare-o com encontrar muitas linhas awk / grep / sed que usam deus sabe que tipo de regex no meio de um script longo - você não tem idéia do que está fazendo lá, a menos que haja comentários.

  • você pode depurar funções anexando set -xe set +x. Depois de saber que o restante do código funciona bem, você pode usar esse truque para se concentrar na depuração apenas dessa 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 o usei algumas vezes para tornar meu código muito mais profissional. Além disso, parse_args()com a getoptsfunção é 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 ou Java ou Vala, mas tem uma experiência limitada no bash. Quanto à eficiência, não há muito o que você pode 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 niceuma função:

nice -10 resource_hungry_function

Comparado a chamar agradável em cada linha de código, isso diminui muita digitação E pode ser usado convenientemente quando você deseja que apenas uma parte do seu script seja executada com prioridade mais baixa.

A execução de funções em segundo plano, na minha opinião, também ajuda quando você deseja que várias instruções sejam executadas em segundo plano.

Alguns dos exemplos em que usei esse estilo:

Sergiy Kolodyazhnyy
fonte
3
Não tenho certeza se você deve levar as sugestões desse artigo muito a sério. Concedido, ele tem algumas boas idéias, mas claramente não é alguém usado para fazer shell scripts. Nem uma única variável em qualquer dos exemplos é citado (!) E sugere o uso de MAIÚSCULAS nomes de variáveis que muitas vezes é uma idéia muito ruim, uma vez que pode entrar em conflito com env existente Vars. Seus pontos nesta resposta fazem sentido, mas o artigo vinculado parece ter sido escrito por alguém que está acostumado a outros idiomas e está tentando forçar o estilo deles ao bash.
terdon
11
@terdon Voltei ao artigo e reli-o. O único lugar em que o autor menciona a nomeação de variáveis ​​em maiúsculas é em "Variáveis ​​Globais Imutáveis". Se você considerar variáveis ​​globais como aquelas que precisam estar no ambiente da função, faz sentido torná-las capital. Na nota lateral, o manual do bash não declara a convenção para maiúsculas e minúsculas. Mesmo aqui, a resposta aceita diz "geralmente" e o único "padrão" é do Google, que não representa todo o setor de TI.
Sergiy Kolodyazhnyy
@terdon em outra nota, concordo 100% de que a citação variável deveria ter sido mencionada no artigo, e isso também foi mencionado nos comentários no blog. Além disso, eu não julgaria alguém usando esse estilo de codificação, independentemente de estar ou não acostumado a outro idioma. Toda essa pergunta e respostas mostram claramente que há vantagens, e o grau de pessoa com o qual eles estão acostumados a outro idioma é provavelmente irrelevante aqui.
Sergiy Kolodyazhnyy
11
@terdon bem, o artigo foi publicado como parte do material "fonte". Eu poderia ter postado tudo como minhas próprias opiniões, mas só tinha que dar crédito a algumas das coisas que aprendi no artigo e que tudo isso veio da pesquisa ao longo do tempo. A página do autor do linkedin mostra que eles têm uma boa experiência com Linux e TI em geral, então acho que o artigo realmente não mostra isso, mas confio na sua experiência quando se trata de Linux e scripts de shell, então você pode estar certo .
Sergiy Kolodyazhnyy
11
Essa é uma excelente resposta, mas também gostaria de acrescentar que o escopo variável no Bash é descolado. Por esse motivo, prefiro declarar minhas variáveis ​​dentro de funções usando locale chamando tudo por meio da main()função. Isso torna as coisas muito mais fáceis de gerenciar e você pode evitar uma situação potencialmente confusa.
Housni
65

Legibilidade é uma coisa. Mas há mais na modularização do que apenas isso. (A semi-modularização talvez seja mais correta para as funções.)

Nas funções, você pode manter algumas variáveis ​​locais, o que aumenta a confiabilidade , diminuindo a chance de as coisas ficarem bagunçadas.

Outro profissional de 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ê poderá entrar no mundo da multithreading ou multiprocessing no mundo Bash. Depois de aprender a fazer as coisas em funções, você estará bem equipado para o passo em paralelo.

Mais um ponto a acrescentar. Como o Etsitpab Nioliv observa no comentário abaixo, é fácil redirecionar das funções como uma entidade coerente. Mas há mais um aspecto dos redirecionamentos com funções. Ou seja, os redirecionamentos podem ser definidos ao longo da definição da função. Por exemplo.:

f () { echo something; } > log

Agora, nenhum redirecionamento explícito é necessário pelas 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

Tomasz
fonte
55
Resposta muito boa, embora fosse muito melhor se fosse dividida em funções.
Pierre Arlaud
11
Talvez acrescentar que funções lhe permitem importar esse script em outro script (usando sourceou . scriptname.sh, e usar essas funções como-se que eles estavam em seu novo script.
SnakeDoc
Isso já está coberto em outra resposta.
Tomasz
11
Obrigado. Mas prefiro deixar que outras pessoas sejam importantes também.
Tomasz
7
Hoje enfrentei um caso em que tive que redirecionar parte da saída de um script para um arquivo (para enviá-lo por email) em vez de ecoar. Eu simplesmente tive que executar o myFunction >> myFile para redirecionar a saída das funções desejadas. Bastante conveniente. Pode ser relevante.
Etsitpab Nioliv
39

No meu comentário, mencionei três vantagens de funções:

  1. Eles são mais fáceis de testar e verificar a correção.

  2. As funções podem ser facilmente reutilizadas (originadas) em scripts futuros

  3. Seu chefe gosta deles.

E nunca subestime a importância do número 3.

Gostaria de abordar mais uma questão:

... portanto, poder trocar arbitrariamente a ordem de execução não é algo que geralmente estaríamos fazendo. Por exemplo, você não iria de repente querem colocar declare_variablesdepois walk_into_bar, que iria quebrar 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_barrequer uma variável que não é usada em outro lugar, 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 mais simples.

Idealmente, as funções devem ser fáceis de testar individualmente. Se, por causa das interações, elas não são fáceis de testar, isso é um sinal de que elas podem se beneficiar da refatoração.

John1024
fonte
Eu diria que às vezes é sensato modelar e impor essas dependências, versus refatorar para evitá-las (já que se houver uma quantidade suficiente delas e elas são suficientemente peludas, isso pode levar a um caso em que as coisas não são mais modularizadas em funções). Um caso de uso muito complicado uma vez inspirou uma estrutura para fazer exatamente isso .
Charles Duffy
4
O que precisa ser dividido em funções deve ser, mas o exemplo leva muito longe. Eu acho que o único que realmente me incomoda é a função de declaração variável. Variáveis ​​globais, especialmente estáticas, devem ser definidas globalmente em uma seção comentada dedicada a esse propósito. Variáveis ​​dinâmicas devem ser locais para as funções que as utilizam e modificam.
Xalorous
@Xalorous Eu já vi práticas 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 em um arquivo externo ... Concordo que deveria ser mais limpo separar definição e inicialização, mas raramente você tem que dobrar se submeter ao número vantagem de 3;-)
Hastur
14

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 você não precise se preocupar em como as coisas são feitas. Ao mesmo tempo, o código se torna mais legível (e passível de manutenção) e 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 levantar uma sobrancelha.

contra-modo
fonte
Resposta subestimada IMHO. Você sugere declarar as variáveis ​​na mainfunção / método, então?
David Tabernero M.
13

Embora eu concorde totalmente com a reutilização , a legibilidade e o beijo delicado dos chefes, mas há outra vantagem das funções no : escopo variável . Como mostra o LDP :

#!/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 em scripts shell do mundo real, mas parece uma boa ideia para scripts mais complexos. Reduzir a coesão ajuda a evitar erros nos quais você está enfrentando uma variável esperada em outra parte do código.

Reutilização geralmente significa criar uma biblioteca comum de funções e sourceinserir essa biblioteca em todos os seus scripts. Isso não os ajudará a correr mais rápido, mas ajudará você a escrevê-los mais rapidamente.

filhotes
fonte
11
Poucas pessoas estão usando explicitamente local, mas acho que a maioria das pessoas que escreve scripts divididos em funções ainda segue o princípio do design. Usign localapenas torna mais difícil a introdução de bugs.
Voo
localdisponibiliza variáveis ​​para a função e seus filhos, portanto é muito bom ter uma variável que possa ser transmitida da função A, mas indisponível para a função B, que pode querer ter variável com o mesmo nome, mas com finalidade diferente. Então isso é bom para definir o escopo e, como disse o Voo - menos bugs
Sergiy Kolodyazhnyy 08/10
10

Um motivo completamente diferente do que já foi fornecido em outras respostas: um motivo pelo qual essa técnica é usada algumas vezes, em que a única declaração de não definição de função no nível superior é uma chamada para main, é garantir que o script não faça acidentalmente nada desagradável se o script estiver truncado. O script pode ser truncado se for canalizado do processo A para o processo B (o shell) e o processo A for encerrado por qualquer motivo antes de terminar de escrever o script inteiro. É provável que isso aconteça se o processo A buscar o script de um recurso remoto. Embora, por razões de segurança, não seja uma boa ideia, é algo que é feito e alguns scripts foram modificados para antecipar o problema.

hvd
fonte
5
Interessante! Mas acho preocupante que alguém precise cuidar dessas coisas em cada um dos programas. Por outro lado, exatamente esse main()padrão é comum no Python, onde se usa if __name__ == '__main__': main()no final do arquivo.
Martin Ueding 30/09/16
11
O idioma python tem a vantagem de permitir que outros scripts importo script atual sem executar main. Suponho que um guarda semelhante possa ser colocado em um script bash.
Jake Cobb
@ Jake Cobb Sim. Agora faço isso em todos os novos scripts bash. Eu tenho um script que contém uma infraestrutura principal de funções usadas por todos os novos scripts. Esse script pode ser originado ou executado. Se originada, sua função principal não é executada. A detecção da origem versus a execução ocorre pelo fato de o BASH_SOURCE conter o nome do script em execução. Se for o mesmo que o script principal, o script está sendo executado. Caso contrário, está sendo fornecido.
DocSalvager
7

Um processo requer uma sequência. A maioria das tarefas é seqüencial. Não faz sentido mexer com a ordem.

Mas o grande problema da programação - que inclui scripts - é o teste. Teste, teste, teste. Quais scripts de teste você possui atualmente para validar a correção de seus scripts?

Seu chefe está tentando guiá-lo de um roteirista para um programador. Esta é uma boa direção a seguir. As pessoas que vierem depois de você irão gostar de você.

MAS. Lembre-se sempre de suas raízes orientadas ao processo. Se fizer sentido ordenar as funções na sequência em que são executadas, faça isso, pelo menos como primeira passagem.

Mais tarde, você verá que algumas de suas funções estão lidando com entradas, outras saídas, outras processando, outras modelando dados e outras manipulando os dados; portanto, pode ser inteligente agrupar métodos semelhantes, talvez até movê-los para arquivos separados .

Mais tarde, você pode perceber que agora escreveu bibliotecas de pequenas funções auxiliares usadas em muitos de seus scripts.

Dewi Morgan
fonte
7

Comentários e espaçamento não podem chegar nem perto da legibilidade que as funções podem, como demonstrarei. Sem funções, você não pode ver a floresta para as árvores - grandes problemas se escondem entre muitas linhas de detalhes. Em outras palavras, as pessoas não podem se concentrar simultaneamente nos detalhes e no quadro geral. Isso pode não ser óbvio em um script curto; contanto que permaneça curto, pode ser legível o suficiente. O software fica maior, porém, 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 esta:

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)

Quando você chegasse na metade ou até 5%, já teria esquecido quais foram os primeiros passos. Você não conseguiu identificar a maioria dos problemas, porque não podia ver a floresta para as árvores. Compare com 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ê notará que esqueceu de fazer o café e provavelmente esqueceu de sit_down () no final. Quando sua mente está pensando nos detalhes das expressões regulares grep e awk, você não pode estar pensando em um cenário geral - "e se não houver café feito"?

As funções permitem principalmente que você veja o quadro geral e observe que 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.

Também há outros benefícios discutidos em outras respostas, é claro. Outro benefício não claramente indicado 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 precisa apenas olhar as outras 6 linhas dessa função para encontrar tudo o que poderia ter sido afetado por esse problema e tudo o que poderia fizeram com que estivesse errado. Sem funções (apropriadas), tudo e qualquer coisa no sistema inteiro pode ser uma causa de $ foo estar incorreta, e tudo e qualquer coisa e tudo podem ser afetados por $ foo. Portanto, você não pode corrigir com segurança $ foo sem reexaminar todas as linhas do programa. Se $ foo for local para uma função,

Ray Morris
fonte
11
Isso não é bashsintaxe. É uma pena, no entanto; Eu não acho que haja uma maneira de passar informações para funções como essa. (ou seja, pour();< coffee). Parece mais c++ou php(acho).
vozes
2
@ tjt263 sem os parênteses, é sintaxe do bash: despeje o café. Com parens, é praticamente qualquer outro idioma. :)
Ray Morris
6

Alguns truques relevantes sobre programação:

  • Seu programa mudará, mesmo que seu chefe insista que esse não é o caso.
  • Somente código e entrada afetam o comportamento do programa.
  • Nomear é difícil.

Os comentários começam como uma brecha por não serem capazes de expressar suas idéias claramente no código * e pioram (ou simplesmente erram) com a mudança. Portanto, se possível, expresse conceitos, estruturas, raciocínio, semântica, fluxo, tratamento de erros e qualquer outra coisa pertinente ao entendimento do código como código.

Dito isto, as funções do Bash têm alguns problemas não encontrados na maioria dos idiomas:

  • O namespacing é terrível no Bash. Por exemplo, esquecer de usar a localpalavra - chave resulta em poluir o espaço para nome global.
  • Usando local foo="$(bar)"resultados na perda do código de saída debar .
  • Como não há parâmetros nomeados, você deve ter em mente o que "$@"significa em diferentes contextos.

* Sinto muito se isso ofende, mas depois de usar os comentários por alguns anos e desenvolvê-los sem eles por mais anos, fica bem claro o que é superior.

** Ainda é necessário o uso de comentários para licenciamento, documentação da API e similares.

l0b0
fonte
I definir quase todas as variáveis locais, declarando-os como nula no início da função ... local foo=""Em seguida, colocá-los usando a execução de comandos para agir sobre o resultado ... foo="$(bar)" || { echo "bar() failed"; return 1; }. Isso nos tira da função rapidamente quando um valor necessário não pode ser definido. As chaves são necessárias para garantir que a return 1execução seja feita apenas em caso de falha.
DocSalvager
6

Tempo é dinheiro

Existem outras boas respostas que esclarecem 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.

Quero me concentrar em uma expectativa: em um ambiente de trabalho "tempo é dinheiro" . Portanto, a ausência de bugs e o desempenho do seu código são avaliados em conjunto com legibilidade , capacidade de teste, manutenção, refactorabilidade, reutilização ...

Escrever em "módulos" um código diminuirá o tempo de leitura necessário não apenas pelo codificador em si, mas também o tempo usado pelos testadores ou pelo chefe. Além disso, observe que o tempo de um chefe geralmente é pago mais do que o tempo de um codificador e que seu chefe avaliará a qualidade do seu trabalho.

Além disso, escrevendo em "módulos" independentes um código (mesmo um script bash) permitirá que você trabalhe "paralelamente" com outro componente de sua equipe, reduzindo o tempo total de produção e utilizando, na melhor das hipóteses, a experiência do single, para revisar ou reescrever uma peça com nenhum efeito colateral nos outros, para reciclar o código que você acabou de escrever "como está"para outro programa / script, criar bibliotecas (ou bibliotecas de trechos), reduzir o tamanho geral e a probabilidade de erros relacionados, depurar e testar minuciosamente cada parte ... e, claro, organizará na seção lógica seu programa / script e aprimore sua legibilidade. Tudo o que economizará tempo e dinheiro. A desvantagem é que você precisa seguir os padrões e comentar suas funções (que você ainda precisa fazer em um ambiente de trabalho).

Aderir a um padrão atrasará seu trabalho no início, mas acelerará o trabalho de todos os outros (e também de você) posteriormente. De fato, quando a colaboração cresce 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 precisam ser definidas globalmente e não em uma função, posso entender um padrão que as inicialize em uma função declare_variables()denominada sempre chamada na primeira linha da main()primeira ...

Por último, mas não menos importante, não subestime a possibilidade nos editores modernos de código fonte de mostrar ou ocultar rotinas seletivamente separadas ( dobragem de código ). Isso manterá o código compacto e concentrará o usuário economizando novamente.

insira a descrição da imagem aqui

Aqui acima, você pode ver como é desdobrado apenas a walk_into_bar()função. Mesmo os outros tinham 1000 linhas cada, você ainda podia controlar todo o código em uma única página. Observe que está dobrada até a seção em que você vai declarar / inicializar as variáveis.

Hastur
fonte
2

Além dos motivos dados em outras respostas:

  1. Psicologia: um programador cuja produtividade está sendo medida em linhas de código terá um incentivo para escrever código desnecessariamente detalhado. Quanto mais o gerenciamento estiver focado nas linhas de código, mais incentivo o programador terá para expandir seu código com complexidade desnecessária. Isso é indesejável, pois a complexidade aumentada pode levar ao aumento do custo de manutenção e ao aumento do esforço necessário para a correção de erros.
agc
fonte
11
Não é uma resposta tão ruim, como dizem os votos negativos. Nota: agc diz que também é uma possibilidade e, sim, é. Ele não diz que seria a única possibilidade, e não acusa ninguém, apenas afirma os fatos. Embora eu ache que hoje quase não seja ouvido um trabalho direto no estilo "linha de código" -> "$$", indiretamente, é bastante comum que sim, a massa do código produzido conte pelos líderes / chefes.
user259412
2

Outro motivo que geralmente é esquecido é a análise de sintaxe do bash:

set -eu

echo "this shouldn't run"
{
echo "this shouldn't run either"

Obviamente, esse script contém um erro de sintaxe e o bash não deve executá-lo, certo? Errado.

~ $ bash t1.sh
this shouldn't run
t1.sh: line 7: syntax error: unexpected end of file

Se empacotá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
Hubert Grzeskowiak
fonte