Utilizando Arrays Chave-Valor do Bash em Shell Scripting

ShellBeginner
Pratique Agora

Introdução

Este tutorial irá guiá-lo através do processo de compreensão e utilização de arrays chave-valor (também conhecidos como arrays associativos) em Bash para seus scripts de shell. Arrays chave-valor são estruturas de dados poderosas que permitem armazenar e recuperar dados usando chaves descritivas em vez de índices numéricos.

Ao final deste tutorial, você será capaz de criar, manipular e usar arrays chave-valor em seus scripts Bash para organizar dados de forma mais eficaz e resolver problemas que seriam difíceis com arrays numéricos tradicionais.

Criando Seu Primeiro Array Chave-Valor em Bash

Arrays chave-valor em Bash (também chamados de arrays associativos) permitem associar valores a chaves específicas, de forma semelhante aos dicionários em Python ou objetos em JavaScript. Isso os torna ideais para armazenar dados estruturados onde os itens são identificados por nomes em vez de posições.

Sintaxe Básica

Para trabalhar com arrays chave-valor em Bash, você deve primeiro declará-los usando a opção -A:

declare -A myarray

Isso cria um array chave-valor vazio chamado myarray. A flag -A especifica que este é um array associativo (chave-valor).

Adicionando Elementos ao Array

Vamos criar um array chave-valor para armazenar informações sobre diferentes frutas:

  1. Abra um novo terminal no WebIDE se um já não estiver aberto
  2. Crie um novo arquivo de script clicando em "File > New File" no WebIDE
  3. Salve o arquivo como fruit_array.sh no diretório /home/labex/project
  4. Adicione o seguinte código ao arquivo:
#!/bin/bash

## Declare a key-value array
declare -A fruits

## Add elements to the array
fruits["apple"]="red"
fruits["banana"]="yellow"
fruits["grape"]="purple"
fruits["orange"]="orange"

## Print a specific element
echo "The color of an apple is ${fruits["apple"]}"

## Print all values
echo "All fruit colors: ${fruits[@]}"

## Print all keys
echo "All fruits: ${!fruits[@]}"
  1. Salve o arquivo (Ctrl+S ou File > Save)
  2. Torne o script executável com o seguinte comando no terminal:
chmod +x fruit_array.sh
  1. Execute o script:
./fruit_array.sh

Você deve ver uma saída semelhante a esta:

The color of an apple is red
All fruit colors: red yellow purple orange
All fruits: apple banana grape orange

Entendendo a Saída

  • ${fruits["apple"]}: Esta sintaxe recupera o valor associado à chave "apple"
  • ${fruits[@]}: Isso retorna todos os valores no array
  • ${!fruits[@]}: O símbolo ! antes do nome do array retorna todas as chaves no array

Arrays chave-valor em Bash permitem que você acesse dados diretamente usando nomes significativos em vez de ter que lembrar posições numéricas, tornando seus scripts mais legíveis e fáceis de manter.

Manipulando Arrays Chave-Valor em Bash

Agora que você entende os conceitos básicos de arrays chave-valor, vamos explorar como manipulá-los. Nesta etapa, você aprenderá como modificar valores existentes, adicionar novos elementos, remover elementos e verificar se uma chave existe.

Criando um Novo Script

  1. Crie um novo arquivo chamado array_operations.sh no diretório /home/labex/project
  2. Adicione o seguinte código ao arquivo:
#!/bin/bash

## Declare a key-value array
declare -A user_info

## Add initial elements
user_info["name"]="John Doe"
user_info["email"]="john@example.com"
user_info["age"]="30"
user_info["city"]="New York"

## Display initial array content
echo "--- Initial user information ---"
for key in "${!user_info[@]}"; do
  echo "$key: ${user_info[$key]}"
done

## Modify an existing value
user_info["age"]="31"

## Add a new key-value pair
user_info["country"]="USA"

## Check if a key exists
if [[ -v user_info["email"] ]]; then
  echo -e "\nEmail exists: ${user_info["email"]}"
else
  echo -e "\nEmail does not exist"
fi

## Remove an element
unset 'user_info[city]'

## Display the modified array
echo -e "\n--- Modified user information ---"
for key in "${!user_info[@]}"; do
  echo "$key: ${user_info[$key]}"
done

## Count the number of elements
echo -e "\nNumber of elements: ${#user_info[@]}"
  1. Salve o arquivo (Ctrl+S ou File > Save)
  2. Torne o script executável:
chmod +x array_operations.sh
  1. Execute o script:
./array_operations.sh

Você deve ver uma saída semelhante a esta:

--- Initial user information ---
name: John Doe
email: john@example.com
age: 30
city: New York

Email exists: john@example.com

--- Modified user information ---
name: John Doe
country: USA
email: john@example.com
age: 31

Number of elements: 4

Operações de Chave Explicadas

  • Modificando valores: Simplesmente atribua um novo valor a uma chave existente: user_info["age"]="31"
  • Adicionando novos elementos: Use a mesma sintaxe da atribuição inicial: user_info["country"]="USA"
  • Verificando se uma chave existe: Use o operador de teste -v: [[ -v user_info["email"] ]]
  • Removendo elementos: Use o comando unset: unset 'user_info[city]'
  • Contando elementos: Use ${#array[@]} para obter o número de elementos
  • Iterando pelos elementos: Use um loop for com ${!array[@]} para obter todas as chaves

Observe como o par chave-valor city é removido na saída modificada, e um novo par chave-valor country foi adicionado. Além disso, o valor de age foi atualizado de 30 para 31.

Essas operações são essenciais ao trabalhar com dados dinâmicos em seus scripts, permitindo que você atualize informações conforme necessário.

Criando um Gerenciador de Configuração Prático

Agora que você entende como criar e manipular arrays chave-valor, vamos construir algo prático. Nesta etapa, você criará um gerenciador de configuração simples que carrega configurações de um arquivo de configuração, armazena-as em um array chave-valor e permite que você as acesse.

Etapa 1: Criar um Arquivo de Configuração

Primeiro, vamos criar um arquivo de configuração com algumas configurações de exemplo:

  1. Crie um novo arquivo chamado app_config.txt no diretório /home/labex/project
  2. Adicione o seguinte conteúdo ao arquivo:
database_host=localhost
database_port=3306
database_user=admin
database_password=secret123
app_name=MyAwesomeApp
debug_mode=true
max_connections=100
  1. Salve o arquivo

Etapa 2: Criar o Script do Gerenciador de Configuração

Agora, vamos criar um script que lerá este arquivo de configuração e armazenará seu conteúdo em um array chave-valor:

  1. Crie um novo arquivo chamado config_manager.sh no diretório /home/labex/project
  2. Adicione o seguinte código ao arquivo:
#!/bin/bash

## Define the path to the configuration file
CONFIG_FILE="/home/labex/project/app_config.txt"

## Declare a key-value array for the configuration
declare -A config

## Function to load configuration from file
load_config() {
  local file=$1

  ## Check if the file exists
  if [[ ! -f "$file" ]]; then
    echo "Error: Configuration file '$file' not found."
    return 1
  fi

  ## Read the file line by line
  while IFS='=' read -r key value; do
    ## Skip empty lines and comments
    if [[ -z "$key" || "$key" == \#* ]]; then
      continue
    fi

    ## Store the key-value pair in the array
    config["$key"]="$value"
  done < "$file"

  echo "Configuration loaded successfully from '$file'"
  return 0
}

## Function to get a configuration value
get_config() {
  local key=$1
  local default=$2

  ## Check if the key exists
  if [[ -v config["$key"] ]]; then
    echo "${config["$key"]}"
  else
    echo "$default"
  fi
}

## Function to display all configuration
display_config() {
  echo "--- Configuration Settings ---"
  for key in "${!config[@]}"; do
    echo "$key = ${config[$key]}"
  done
}

## Load the configuration
load_config "$CONFIG_FILE"

## Display all configuration settings
display_config

## Example of getting specific configuration values
echo -e "\n--- Example Usage ---"
db_host=$(get_config "database_host" "127.0.0.1")
db_port=$(get_config "database_port" "5432")
db_user=$(get_config "database_user" "root")
db_pass=$(get_config "database_password" "")
app_name=$(get_config "app_name" "DefaultApp")
debug_mode=$(get_config "debug_mode" "false")

echo "Database connection: $db_user@$db_host:$db_port"
echo "Application name: $app_name"
echo "Debug mode: $debug_mode"

## Example of getting a non-existent value (will use default)
timeout=$(get_config "connection_timeout" "30")
echo "Connection timeout: $timeout (default value used)"
  1. Salve o arquivo (Ctrl+S ou File > Save)
  2. Torne o script executável:
chmod +x config_manager.sh
  1. Execute o script:
./config_manager.sh

Você deve ver uma saída semelhante a esta:

Configuration loaded successfully from '/home/labex/project/app_config.txt'
--- Configuration Settings ---
database_host = localhost
database_port = 3306
database_user = admin
database_password = secret123
app_name = MyAwesomeApp
debug_mode = true
max_connections = 100

--- Example Usage ---
Database connection: admin@localhost:3306
Application name: MyAwesomeApp
Debug mode: true
Connection timeout: 30 (default value used)

Entendendo o Gerenciador de Configuração

O script que você criou faz várias coisas importantes:

  1. Ele lê pares chave-valor de um arquivo de configuração
  2. Ele armazena esses pares em um array chave-valor
  3. Ele fornece funções para:
    • Carregar a configuração de um arquivo
    • Obter valores de configuração específicos com valores padrão (default fallbacks)
    • Exibir todas as configurações

Este padrão é comumente usado em aplicações do mundo real para gerenciar configurações. Os principais benefícios são:

  • Configuração centralizada: Todas as configurações estão em um só lugar
  • Valores padrão: Se uma configuração estiver faltando, um valor padrão pode ser usado
  • Acesso fácil: As configurações podem ser acessadas por nome
  • Flexibilidade: A configuração pode ser atualizada sem alterar o script

Este exemplo demonstra como arrays chave-valor podem ser usados para resolver problemas práticos em scripts de shell. Você pode estendê-lo adicionando funções para salvar as alterações de volta no arquivo de configuração ou para validar as configurações.

Nesta etapa final, criaremos um script prático orientado a menu que usa arrays chave-valor para armazenar e processar as seleções do usuário. Este exemplo demonstra como os arrays chave-valor podem ser usados para criar aplicações de linha de comando mais interativas e fáceis de usar.

  1. Crie um novo arquivo chamado menu_system.sh no diretório /home/labex/project
  2. Adicione o seguinte código ao arquivo:
#!/bin/bash

## Declare a key-value array for menu options
declare -A menu_options
menu_options["1"]="Display system information"
menu_options["2"]="Check disk usage"
menu_options["3"]="List running processes"
menu_options["4"]="View network connections"
menu_options["q"]="Quit"

## Declare a key-value array for commands to execute
declare -A menu_commands
menu_commands["1"]="display_system_info"
menu_commands["2"]="check_disk_usage"
menu_commands["3"]="list_processes"
menu_commands["4"]="view_network"

## Function to display system information
display_system_info() {
  echo -e "\n--- System Information ---"
  echo "Hostname: $(hostname)"
  echo "Kernel version: $(uname -r)"
  echo "System uptime: $(uptime -p)"
  echo "CPU information: $(grep 'model name' /proc/cpuinfo | head -1 | cut -d ':' -f 2 | xargs)"
  echo "Total memory: $(free -h | grep Mem | awk '{print $2}')"
}

## Function to check disk usage
check_disk_usage() {
  echo -e "\n--- Disk Usage ---"
  df -h | grep -v tmp
}

## Function to list running processes
list_processes() {
  echo -e "\n--- Top 10 Processes by Memory Usage ---"
  ps aux --sort=-%mem | head -11
}

## Function to view network connections
view_network() {
  echo -e "\n--- Active Network Connections ---"
  netstat -tuln | grep LISTEN
}

## Function to display the menu
display_menu() {
  echo -e "\n=== System Utility Menu ==="
  for key in 1 2 3 4 q; do
    echo "$key. ${menu_options[$key]}"
  done
  echo -e "\nPlease enter your choice:"
}

## Main loop
while true; do
  ## Display the menu
  display_menu

  ## Read user choice
  read -r choice

  ## Check if choice is valid
  if [[ -v menu_options["$choice"] ]]; then
    ## Exit if user chose quit
    if [[ "$choice" == "q" ]]; then
      echo "Exiting. Goodbye!"
      exit 0
    fi

    ## Execute the corresponding command
    if [[ -v menu_commands["$choice"] ]]; then
      ## Call the function associated with the choice
      ${menu_commands["$choice"]}
    fi
  else
    echo "Invalid option. Please try again."
  fi

  ## Pause for user to read output
  echo -e "\nPress Enter to continue..."
  read -r
done
  1. Salve o arquivo (Ctrl+S ou File > Save)
  2. Torne o script executável:
chmod +x menu_system.sh
  1. Execute o script:
./menu_system.sh
  1. Experimente as diferentes opções de menu digitando o número correspondente e, em seguida, pressione Enter quando solicitado para retornar ao menu. Digite q para sair do programa quando terminar.

Este script demonstra vários usos avançados de arrays chave-valor:

  1. Opções de Menu: O array menu_options mapeia números de opção para texto descritivo
  2. Mapeamento de Comando: O array menu_commands mapeia números de opção para nomes de funções
  3. Execução Dinâmica: O script usa o valor de um array para determinar qual função chamar

Os benefícios de usar arrays chave-valor neste sistema de menu incluem:

  • Manutenibilidade: Adicionar ou modificar opções de menu requer apenas a atualização dos arrays
  • Legibilidade: O código mostra claramente qual comando corresponde a qual opção de menu
  • Flexibilidade: Você pode facilmente reordenar os itens do menu sem alterar as chamadas de função

Este padrão é útil para criar ferramentas de linha de comando interativas que são fáceis de manter e estender.

Principais Conclusões

Ao longo deste tutorial, você aprendeu:

  1. Como criar e inicializar arrays chave-valor em Bash
  2. Como acessar, modificar e remover elementos de arrays chave-valor
  3. Como iterar sobre chaves e valores em um array chave-valor
  4. Como usar arrays chave-valor para armazenar dados de configuração
  5. Como criar um sistema de menu interativo usando arrays chave-valor

Essas técnicas podem ser aplicadas a uma ampla gama de tarefas de script de shell, desde o armazenamento simples de dados até aplicações interativas complexas.

Resumo

Neste tutorial, você explorou o poder e a versatilidade dos arrays chave-valor do Bash. Começando com o básico, você aprendeu como criar e acessar arrays chave-valor, e então progrediu para operações mais avançadas, como modificar, adicionar e remover elementos.

Você aplicou esse conhecimento para criar exemplos práticos, incluindo um gerenciador de configuração que lê configurações de um arquivo e um script de utilidade orientado a menu que demonstra como os arrays chave-valor podem ser usados para criar aplicações interativas de linha de comando.

Arrays chave-valor fornecem uma maneira poderosa de organizar e acessar dados em seus scripts Bash. A capacidade de usar chaves descritivas em vez de índices numéricos torna seus scripts mais legíveis e fáceis de manter, especialmente ao lidar com estruturas de dados complexas.

Agora que você tem uma sólida compreensão dos arrays chave-valor em Bash, você pode usá-los para aprimorar seus scripts de shell e resolver uma ampla gama de desafios de programação de forma mais eficiente.