Pesquisa de site

Compreendendo e escrevendo funções em Shell Scripts - Parte VI


As funções desempenham um papel importante em qualquer linguagem de programação. Como muitas linguagens de programação reais, o bash possui funções que são usadas com implementação limitada.

O que são funções?

Na programação, as funções são seções nomeadas de um programa que executa uma tarefa específica. Nesse sentido, uma função é um tipo de procedimento ou rotina. Quando uma função é chamada, o programa sai da seção atual do código e começa a executar a primeira linha dentro da função. Sempre que houver código repetitivo ou quando uma tarefa se repetir, considere usar uma função.

Por exemplo, considere o caso em que precisamos encontrar o fatorial de um número em vários estágios de um programa específico. Em vez de escrever o código inteiro (para calcular o fatorial) todas as vezes, podemos escrever aquela parte do código que calcula o fatorial uma vez dentro de um bloco e reutilizá-lo em várias ocasiões.

Por que escrevemos funções?

  1. Isso nos ajuda a reutilizar o código.
  2. Melhore a legibilidade do programa.
  3. Uso eficiente de variáveis dentro do programa.
  4. Permite-nos testar o programa parte por parte.
  5. Exibe o programa como um conjunto de subetapas.
Funções em scripts de shell

A sintaxe geral para escrever funções em shell script inclui as seguintes maneiras.

function func_name {
	. . .
	commands
	. . .
}

or

func_name ( ) {
	. . .
	commands
	. . .
}

Opening curly braces can also be used in the second line as well.

func_name ( )
{
	. . .
	commands
	. . .
}

Você está sempre livre para escrever comandos válidos dentro desses blocos de funções, como fazemos normalmente em scripts shell. Agora vamos tentar escrever um script simples com uma pequena função dentro dele.

#!/bin/bash

call_echo ( ) {
	echo ‘This is inside function’
}

op=$1

if [ $# -ne 1 ]; then
	echo "Usage: $0 <1/0>"
else
	if [ $1 = 0 ] ; then
		echo ‘This is outside function’
	elif [ $1 = 1 ] ; then
		call_echo
	else
		echo ‘Invalid argument’
	fi
fi

exit 0

A definição da função deve preceder a primeira chamada a ela. Não há nada como ‘declarar a função’ antes de chamá-la. E sempre podemos aninhar funções dentro de funções.

Nota:- Escrever funções vazias sempre resulta em erros de sintaxe.

Quando a mesma função é definida várias vezes, a versão final é a que é invocada. Vejamos um exemplo.

#!/bin/bash

func_same ( ) {
	echo ‘First definition’
}

func_same ( ) {
	echo ‘Second definition’
}

func_same

exit 0
Funções que recebem parâmetros e retornam valores

Vamos nos aprofundar considerando funções que recebem parâmetros e retornam valores. Para retornar um valor de uma função, usamos o shell ‘return’ integrado. A sintaxe é a seguinte.

func_name ( ) {
	. . .
	commands
	. . .
	return $ret_val
}

Da mesma forma, podemos passar argumentos para as funções separadas por espaços, conforme mostrado abaixo.

func_name $arg_1 $arg_2 $arg_3

Dentro da função podemos acessar os argumentos na ordem $1, $2, $3 e assim por diante. Observe o script de exemplo a seguir para encontrar o máximo de dois números inteiros usando a função para adicionar mais clareza.

#!/bin/bash

USG_ERR=7

max_two ( ) {
	if [ "$1" -eq "$2" ] ; then
		echo 'Equal'
		exit 0
	elif [ "$1" -gt "$2" ] ; then
		echo $1
	else
		echo $2
	fi
}

err_str ( ) {
	echo "Usage: $0 <number1>  <number2>"
	exit $USG_ERR
}

NUM_1=$1
NUM_2=$2
x
if [ $# -ne 2 ] ; then
	err_str
elif [ `expr $NUM_1 : '[0-9]*'` -eq ${#NUM_1} ] ; then
	if [ `expr $NUM_2 : '[0-9]*'` -eq ${#NUM_2} ] ; then  
		max_two $NUM_1 $NUM_2
	else
		err_str
	fi
else
	err_str
fi

exit 0

O texto acima parece um pouco complexo, mas é simples se lermos as linhas. Primeiras linhas if-else if aninhadas para fins de validação, ou seja, para verificar o número e o tipo de argumentos com a ajuda de expressões regulares. Depois disso, chamamos a função com dois argumentos de linha de comando e exibimos o resultado lá. Isso ocorre porque não podemos retornar números inteiros grandes de uma função. Outra maneira de contornar esse problema é usar variáveis globais para armazenar o resultado dentro da função. O script abaixo explica esse método.

#!/bin/bash

USG_ERR=7
ret_val=

max_two ( ) {
	if [ "$1" -eq "$2" ] ; then
		echo 'Equal'
		exit 0
	elif [ "$1" -gt "$2" ] ; then
		ret_val=$1
	else
		ret_val=$2
	fi
}

err_str ( ) {
	echo "Usage: $0 <number1>  <number2>"
	exit $USG_ERR
}

NUM_1=$1
NUM_2=$2

if [ $# -ne 2 ] ; then
	err_str
elif [ `expr $NUM_1 : '[0-9]*'` -eq ${#NUM_1} ] ; then
	if [ `expr $NUM_2 : '[0-9]*'` -eq ${#NUM_2} ] ; then  
		max_two $NUM_1 $NUM_2
		echo $ret_val
	else
		err_str
	fi
else
	err_str
fi

exit 0

Agora experimente alguns problemas interessantes que foram explicados na série anterior de scripts de shell usando funções como a seguir.

  1. Entenda as dicas básicas da linguagem de script do Linux Shell - Parte I
  2. 5 scripts Shell para iniciantes em Linux aprenderem programação Shell - Parte II
  3. Navegando pelo mundo dos scripts BASH do Linux – Parte III
  4. Aspecto matemático da programação Linux Shell – Parte IV
  5. Calculando expressões matemáticas em linguagem Shell Scripting – Parte V

Voltarei com mais informações sobre recursos funcionais, como uso de variáveis locais, recursão, etc., na próxima parte. Fique atualizado com comentários.