-
Notifications
You must be signed in to change notification settings - Fork 7
Introdução
O propósito do projeto bashsrc é manter o estilo de programação funcional do bash adicionando uma implementação genérica de tipos e métodos em paralelo com a programação pipe line padrão.
As bibliotecas disponíveis no projeto foram desenvolvidas em shell script utilizando apenas recursos builtin e coreutils. Cada biblioteca é composta por variáveis, tipos e funções que fornecem uma interface para manipulação de texto, regex, leitura e gravação de arquivos, informações do sistema entre outras.
O projeto foi desenvolvido com o objetivo de ser escalável, isto é, permite o usuário criar suas próprias bibliotecas com funções, métodos e tipos de forma simples e eficiente.
O texto a seguir é um guia rápido e introdutório de como utilizar esses recursos e explorar suas funcionalidades.
Para utilizar os recursos de uma biblioteca é necessário importá-la por meio do comando source ou . seguido pelo nome.
Exemplo:
#!/bin/bash
source biblioteca.shou
#!/bin/bash
. biblioteca.shA importação carrega na memória as funções, tipos e variáveis declaradas, disponibilizando-as em todo o projeto onde foram importadas.
A biblioteca builtin é composta por funções básicas para declaração de tipos, iteração de elementos, loops e etc. Todavia é de suma importância e imprescindível para o funcionamento do eco sistema do bashsrc e cuja importação deve preceder qualquer outra biblioteca.
Ao contrário das demais bibliotecas, suas funções não possuem um prefixo, sendo referenciadas apenas por seu identificador curto.
Protótipo:
funcao
Obs: somente na consulta da documentação o prefixo
builtin.funcaoé requerido.
Exemplo:
Utilizando uma função builtin para converter um número inteiro para binário (base 2).
#!/bin/bash
# Importando
source builtin.sh
# função builtin
bin 255Saída:
11111111
A biblioteca contém um conjunto de funções que realizam tarefas especificas onde a nomenclatura de cada função é prefixada pela 'biblioteca' a qual pertence (exceto builtin).
O protótipo de declaração determina a ordem e o tipo de cada argumento. Todos argumentos que compõe a função são obrigatórios e suporta um tipo especifico de dado, gerando uma mensagem de erro caso seja omitido ou inválido.
Protótipo:
funcao <[tipo1]arg1> <[tipo2]arg2> ... => [tipo]
| | | | |
| | | | |___ Tipo do dado de retorno da função.
| | | |
| | | |__ argumentos variáticos (aceita um ou mais argumentos).
| | |
| | |__ Nome do argumento posicional.
| |
| |__ Tipo do dado suportado pelo argumento (Flag type ou object_t).
|
|__ Identificador válido da função.
object_té um tipo de objeto que pode ser implementado.
O Flag type é um dado mapeado a partir de um expressão de comprimento variável cujo tipo é determinado pela aplicação de um padrão (regex).
A flag indica o tipo de dado suportado pelo argumento cujo valor precisa atender aos critérios de validação.
| Flag | Critérios |
|---|---|
| uint | Inteiro sem sinal. |
| int | Inteiro com sinal. |
| float | Número de precisão com sinal separado por '.' (ponto) ou ',' (vírgula). |
| zone | Fuso horário. |
| char | Caractere único. |
| str | Uma cadeia de caracteres. |
| bool | Booleano (true ou false). |
| var | Identificador de uma variável ou vetor válido. |
| array | Array indexado. (inicializado) |
| map | Array associativo. (inicializado) |
| funcname | Nomenclatura de função válida. |
| func | Identificador de uma função válida. |
| srctype | Identificador de objeto de implementação terminado em _T ou _t. |
| st_member | Identificador de membro da estrutura. |
| bin | Número binário (base 2). |
| hex | Número hexadecimal (base 16). |
| oct | Número octal (base 8). |
| size | Unidade de armazenamento. (12KB, 1MB, 10G, 2TB ...) |
| 12h | Hora no formato 12 horas. (HH:MM -> 1..12) |
| 24h | Hora no formato 24 horas. (HH:MM -> 0..23) |
| date | Data no formato. (DD/MM/YYYY) |
| hour | Hora. (0..23) |
| min | Minutos. (0..59) |
| sec | Segundos. (0..59) |
| mday | Dia do mês. (1..31) |
| mon | Dia da semana. (1..12) |
| year | Ano. inteiro positivo com 4 ou mais dígitos. |
| yday | Dias do ano. (1..366) |
| wday | Dias da semana. (1..7) |
| url | Endereço web. (http|https|ftp|smtp)://www?... |
| Endereço de email. | |
| ipv4 | protocolo ipv4 (32 bits) |
| ipv6 | protocolo ipv6 (128 bits) |
| mac | Endereço MAC Address (xx:xx:xx:xx:xx:xx) |
| slice | Intervalo numérico. [int:int]
|
| uslice | Intervalo numérico positivo [uint:uint]
|
| keyword | Palavra chave que indica que 'type' tem que ser igual a 'name'. (somente getopt.parse) |
| dir | Diretório válido. |
| file | Arquivo padrão. |
| path | Caminho válido. |
| flag | Sequência de caracteres [a-zA-Z_]. |
Além da Flag type as funções também suportam tipos de objetos implementados que contém o sufixo _t ou _T em sua nomenclatura.
Exemplo
Protótipo da função os.open que recebe como argumento um objeto do tipo file_t
func os.open <[file_t]var> <[str]filename> <[uint]flag> => [bool]
Obs: a palavra-chave
funcinforma que o protótipo do objeto é uma função. (somente para documentação)
Outro exemplo é o protótipo da função time.gmtime que recebe uma estrutura que é implementada pelo tipo time_t.
func time.gmtime <[time_t]struct> <[uint]seconds>
Funções com retorno [bool]
Diferentemente dos demais tipos o bool não retorna explicitamente um valor, mas define o código de status da função após a execução; Sendo 0 (verdadeiro) ou != 0 (falso) e que é acessada através da variável $?.
Exemplo:
Utilizando a função str.compare para comparar duas strings e que retorna '0' se forem iguais ou '1' para diferentes.
# Comparando as strings.
str.compare "shell script" "SHELL SCRIPT"
echo $?Saída:
1
Também é possível verificar o status da função executando-a diretamente em um bloco condicional if.
Exemplo:
if str.compare "shell" "shell"; then
echo "Iguais"
else
echo "Diferentes"
fiou
str.compare "shell" "shell" && echo "Iguais" || echo "Diferentes"Saída:
Iguais
Argumentos posicionais:
Cada função possui um identificador exclusivo composto pelo sufixo da biblioteca a qual pertence (se disponível) e que deve ser chamada com os argumentos posicionais dos tipos pré-estabelecidos por seu protótipo de declaração.
A ordem dos argumentos posicionais é obrigatória assim como o total de argumentos suportados pela função.
Protótipo:
Total de argumentos: 4
_______________|_________________
| |
Função $1 $2 $3 $4 -> Argumentos posicionais
| | | | |
string.replace <[str]exp> <[str]old> <[str]new> <[int]count> => [str]
|
Tipo do retorno
É recomendável a utilização das aspas duplas " ou simples ' na passagem dos argumentos para evitar que informações vazem para os demais argumentos posicionais.
Exemplo:
Utilizando a função acima para realizar a substituição de uma string por outra em uma expressão.
#!/bin/bash
source string.sh
string.replace 'Programar em [linguagem] é vida.' 'linguagem' 'shell script' 1Saída:
Programar em [shell script] é vida.
Obs: use aspas duplas
"caso precise expandir o valor de uma variável.
Salvando retorno:
Para capturar o retorno de uma função é necessário chamá-la em um sub-shell utilizando o conjunto de expansão $(...).
var=$(funcao arg1 arg2 ...)Exemplo:
#!/bin/bash
source string.sh
# Texto
texto='Seja livre, use Linux'
# Salvando retorno.
reverso=$(string.reverse "$texto")
# Imprimindo
echo "$reverso"Saída:
xuniL esu ,ervil ajeS
Empilhamento:
O empilhamento é um conjunto de funções cujo o valor de retorno é tratado pela função externa subsequente.
Protótipo:
funcao1 "$(funcao2 "$(funcao 3)")"
Exemplo:
#!/bin/bash
source string.sh
# Texto
texto='Seja livre, use <so>'
# Converte o texto para maiúsculo antes de realizar a substituição.
string.replace "$(string.toupper "$texto")" "<SO>" "LINUX" 1Saída:
SEJA LIVRE, USE LINUX
Obs: a prioridade de expansão acontece de dentro para fora, ou seja, ocorre do sub-shell mais interno para o externo subsequente.
Função como argumento:
Uma função que recebe como argumento outra função que é executada a cada iteração e que recebe como argumento posicional $1 o elemento atual, anexando o valor de retorno da função de iteração.
Veja o protótipo da função fnmap da biblioteca builtin.sh.
(opcional)
|
(função de iteração)[argumentos]
| |
func fnmap <[var]name> <[func]funcname> <[str]args> ...
|
(variável)
Obs:
argsé um argumento variático, ou seja, pode ser especificado um ou mais argumentos dependendo da função de iteração aplicada.
A função fnmap lê os caracteres armazenados em name e cada iteração chama funcname passando como argumento o caractere atual.
Exemplo:
#!/bin/bash
source builtin.sh
# variável
distro='SLACKWARE'
# função de iteração.
colunas(){
# Retorna para 'fnmap' o caractere modificado.
echo "[$1]"
}
fnmap distro colunasSaída:
[S][L][A][C][K][W][A][R][E]
Também é possível passar argumentos para a função de iteração. Veja o exemplo abaixo utilizando a função string.repeat para triplicar os caracteres contidos na expressão.
Exemplo:
#!/bin/bash
source string.sh
distro='SLACKWARE'
fnmap distro string.repeat 3Saída:
SSSLLLAAACCCKKKWWWAAARRREEE
Flag types (var, array, map, func e object_t)
Os argumentos com a flag type var, array, map, func ou object_t são ponteiros para objetos existentes associados ao seu identificador (nome) para acesso direto e que deve ser especificado sem o caractere de expansão $ (cifrão).
Exemplo:
Considere o protótipo da função 'swap' que troca os valores entre variáveis e que recebe dois argumentos do tipo var.
Protótipo:
func swap <[var]name1> <[var]name2>
Código:
# Variáveis
var1=10
var2=20
# Passando argumentos
// * INCORRETO * //
swap $var1 $var2
// * CORRETO * //
swap var1 var2Um map é um array associativo que possui uma estrutura de dados composta por um conjunto de elementos referenciados por uma chave ou valor. As chaves podem ser definas pelo usuário e armazenadas na estrutura.
Para declarar um array associativo utilize os comandos local ou declare com parâmetro -A seguido pelo identificador da variável.
Exemplo:
local -A var=()
declare -A var=()Consulte a documentação para mais detalhes:
help declareouhelp local.
Array é uma estrutura de dados que armazena uma coleção de elementos que são referenciados por um índice, conhecida como array indexado.
Para declarar um array indexado utilize os comandos local ou declare com o parâmetro -a seguido pelo identificador da variável.
Exemplo:
local -a var=()
declare -a var=()Uma variável também pode ser considerada como um array indexado podendo ser referenciada diretamente sem uma declaração explicita.
Exemplo:
var=(item1 item2 ...)
var[10]='item10'Inicializando (array/map)
Funções com argumentos do tipo array ou map precisam ser previamente instanciadas antes passá-las na função.
Exemplo:
Considere o protótipo da função map.list que lista as chaves e valores do map especificado em name.
func map.list <[map]name> => [key|object]
Código:
/* INCORRETO */
# Não é um tipo 'map'
meu_map=''
map.list meu_map
---
/* CORRETO */
# Map
declare -A meu_map=()
map.list meu_mapShell script não possui orientação a objetos, métodos ou heranças. Porém, como qualquer outra linguagem existe o escopo de visibilidade durante a declaração de uma variável e com a abstração adequada é possível a criação de funções que simulam métodos de acesso por entidade.
A função var é responsável por inicializar e implementar os métodos do objeto. Uma variável só pode ser implementada por um único objeto. (veja também: del)
Protótipo:
var varname ... object_t
varnamenome da variável a ser implementada. 'object_' nome do objeto de implementação.
Todo o objeto implementado é global, ou seja, seus métodos são visíveis por todo o código, exceto o valor da variável da entidade que só pode ser acessada dentro do seu escopo de declaração. (exceto struct_t)
Exemplo:
#!/bin/bash
source builtin.sh
source string.sh
# Implementa os objetos.
var var_g string_t
var var_l string_t
var_p='Linux'
funcao(){
# declara 'var_l' como local
local var_l
var_l='Windows'
}
# Chama 'funcao' para atribuir o valor de 'val_l'.
funcao
# Executa o método 'toupper' dos objetos implementados.
echo "var_g = $(var_g.toupper)"
echo "val_l = $(var_l.toupper)"
Saída:
var_p = LINUX
val_l =
Note que apesar do método
val_l.toupperter sido executado com sucesso, nenhum valor foi retornado.
Método/Argumento posicional
Os métodos do objeto recebem o valor ou o identificador da variável implementada como argumento posicional $1 em sua chamada, dependendo do tipo da função pode ser por valor ou referência. De qualquer modo o método deve ser chamado omitindo o seu primeiro argumento.
Exemplo 1:
Veja o protótipo da função string.len que calcula o comprimento de uma string.
func string.len <[str]exp> => [uint]
|
$1
Usando a função:
#!/bin/bash
source string.sh
# Usando a função
string.len "shell script"Saída:
12
Usando o método:
#!/bin/bash
source builtin.sh
source string.sh
# Implementa texto com o tipo 'string_t'.
var texto string_t
# Armazena o texto
texto='shell script'
# Chama o método
texto.lenSaída:
12
Exemplo 2:
Utilizando a função string.repeat para repetir 'N' vezes uma determina string.
Protótipo:
func string.repeat <[str]exp> <[uint]count> => [str]
|
$1
Usando a função:
#!/bin/bash
source builtin.sh
source string.sh
# Chama a função
texto.repeat 'LINUX-' 5
Saída:
LINUX-LINUX-LINUX-LINUX-LINUX-
Usando o método:
#!/bin/bash
source builtin.sh
source string.sh
# Implementa 'texto'.
var texto string_t
# Texto
texto='LINUX-'
# Chama o método
texto.repeat 5
Saída:
LINUX-LINUX-LINUX-LINUX-LINUX-
- E-mail: shellscriptx@gmail.com
- Juliano Santos (SHAMAN)
