Criando funções em scripts bash (Linux/Bash)

Criando funções em scripts bash (Linux/Bash)

Overview

Se você já se encontrou duplicando código em seus scripts bash e se perguntando se haveria uma maneira melhor de fazer as coisas, esta postagem é para você. Aqui, compartilho uma luz sobre como criar, chamar e manipular funções em bash, tornando seus scripts mais limpos e reutilizáveis. Então, pegue sua xícara de café favorita e vamos mergulhar juntos nas maravilhas das funções bash!

Enquanto escrevia um script particularmente grande, percebi que precisaria repetir/reutilizar partes do código e duplicar código é algo que me irrita profundamente. Então pesquisei sobre funções em scripts bash e fiquei semi-feliz com o resultado da pesquisa. Neste post, vou compartilhar o básico sobre como criar e utilizar funções nos scripts bash.

Antes que você saia correndo para refatorar todos aqueles bash scripts que você tem, vale uma nota importante: Diferente das outras linguagens, os bash scripts não permitem retornar valores. Você pode retornar um valor numérico indicando sucesso (sucesso = zero) ou falha (qualquer outro numero).

Caso você tente retornar uma string, vai ser agraciado pela seguinte mensagem:

return: string return: numeric argument required

Calma, não precisa desanimar. Existem formas de conseguir retornar valores após a execução de uma função, mas vou deixar para explicar isso mais para frente. Agora vamos à sintaxe de como criar e chamar as funções:

Declaração de funções

Abaixo estão algumas formas de declarar uma função em um script bash:

Forma 1

nome_da_funcao() {
  # <codigo>
}

Forma 2

function nome_da_funcao() {
  # <codigo>
}

Forma 3

function nome_da_funcao {
  # <codigo>
}

Todas as 3 formas tem o mesmo efeito. Não sei se existe alguma diferença ou incompatibilidade séria entre elas. Acredito que não, pois não vi nenhum alerta nas pesquisas que realizei, mas se descobrir, atualizo o post. 🙂

Para chamar as funções que você criou é simples, basta incluir o nome da função, da mesma forma que você faria com funções nativas do Linux.

Veja este exemplo:

#!/bin/bash

function hello_world {
  echo "Hello World!"
}

hello_world

No exemplo acima, declaramos a função “hello_world” e depois ela é chamada na última linha do script. O resultado vai ser a frase “Hello World!” vai ser escrita no terminal.

Passando argumentos para as funções

Uma parte importante da motivação para criar funções é que ela possa receber argumentos. Esta parte do procedimento é simples e é exatamente igual a passar argumentos para um script. Sendo assim, você pode utilizar a mesma lógica apresentada no post “Recuperando argumentos passados para um script shell” para recuperar os argumentos passados para a função.

A diferença é que, mesmo dentro da função, se você tentar utilizar a variável $0 ($ zero), ela vai possuir o nome do script e não da função.

Veja o exemplo:

#!/bin/bash
function hello_world {
  echo "Hello World!"
  echo "Zero: $0"
  echo "First: $1"
  for arg in "$@"
  do
      i=$((i+1))
      echo "Arg $i: $arg"
  done
}

hello_world foo bar "bacon foo" "bacon bar"

No código acima, adaptei a função “hello_world” para que ela mostre no terminal todos os argumentos que foram passados para ela.

Na última linha do código, eu passo os argumentos: foo, bar, “bacon foo” e “bacon bar” para a função.

O resultado desta função ficaria assim:

Hello World!
Zero: ./t.sh
First: foo
Arg 1: foo
Arg 2: bar
Arg 3: bacon foo
Arg 4: bacon bar

Este exemplo mostra como os argumentos são processados.

Retornando valores

Ok, as funções em si não retornam valores, mas você consegue utilizar variáveis para transferir e verificar estes valores.

A forma mais simples é utilizar uma variável global para armazenar o valor.

#!/bin/bash

function func1 {
  resultado="deu certo"
}

func1
echo "$resultado"

Existe uma alternativa para as variáveis globais… o que é bom, pois algumas pessoas não gostam muito de utilizar estas variáveis. A alternativa é utilizar substituição:

#!/bin/bash

func2() {
  local resultado_interno="deu certo!"
  echo "$resultado_interno"
}

resultado=$(func2)
echo "$resultado"

Se não estiver satisfeito, também existe uma terceira opção, mas acho utiliza-la fica meio confuso na hora de ler o script. A terceira forma é escrever sua função de modo que ela aceite uma variável como argumento, que servirá para armazenar o resultado. Exemplo:

#!/bin/bash

function func3() {
  local __resultado=$1
  local result="deu certo!!"
  eval $__resultado="'$result'"
}

func3 resultado
echo "$resultado"

Da para perceber que fica um pouco mais confuso, mas funciona bem… apesar de depender da função eval.

Ela é uma função onde você constrói um comando através da concatenação de uma série de argumentos, mas isso é um assunto para um possível post futuro.

Bom, neste post mostrei como declarar e chamar um função, como passar e ler os argumentos para ela e como retornar o resultado. Divirta-se otimizando seus scripts bash! 🙂

Espero ter ajudado!