+
+
ocaml
travis
remix
==
+
elm
asm
vault
βˆ‰
haiku
+
+
+
pip
grpc
+
+
+
∫
sails
+
+
+
helm
lua
+
+
::
dns
+
numpy
+
go
+
+
solid
kotlin
react
spacy
+
+
ionic
+
cobol
+
+
+
nuxt
cobol
+
dart
+
django
+
+
aurelia
+
+
+
+=
remix
+
+
<=
+
+
Ο€
+
alpine
+
gradle
->
+
xgboost
+
redhat
notepad++
+
+
vue
+
+
raspbian
+
+
+
backbone
Back to Blog
Bash Arrays: A Comprehensive Guide with Examples πŸ“š
bash arrays scripting

Bash Arrays: A Comprehensive Guide with Examples πŸ“š

Published Mar 5, 2025

Master Bash arrays with this comprehensive guide. Learn indexed arrays, associative arrays, and array manipulation with practical examples and best practices.

12 min read
0 views
Table of Contents

Bash Arrays: A Comprehensive Guide with Examples

Arrays are powerful data structures in Bash that allow you to store multiple values in a single variable. This comprehensive guide will teach you everything about Bash arrays! πŸš€

Introduction to Bash Arrays

Bash supports two types of arrays:

  1. Indexed Arrays: Elements accessed by numeric index (0-based)
  2. Associative Arrays: Elements accessed by string keys (Bash 4.0+)

Indexed Arrays

Declaring Indexed Arrays

# Method 1: Declare and initialize
fruits=("apple" "banana" "orange" "grape")

# Method 2: Declare empty array
declare -a colors

# Method 3: Assign individual elements
animals[0]="cat"
animals[1]="dog"
animals[2]="bird"

# Method 4: Read from command output
files=($(ls *.txt))

# Method 5: Using declare
declare -a numbers=(1 2 3 4 5)

Accessing Array Elements

# Access single element
echo ${fruits[0]}  # apple
echo ${fruits[2]}  # orange

# Access all elements
echo ${fruits[@]}  # apple banana orange grape
echo ${fruits[*]}  # apple banana orange grape

# Get array length
echo ${#fruits[@]}  # 4

# Get length of specific element
echo ${#fruits[1]}  # 6 (length of "banana")

Array Operations

# Adding elements
fruits+=("watermelon")
fruits[5]="mango"

# Modifying elements
fruits[1]="strawberry"

# Deleting elements
unset fruits[2]

# Array slicing
echo ${fruits[@]:1:3}  # Elements from index 1, next 3 elements

# Copy array
new_fruits=("${fruits[@]}")

Associative Arrays

Declaring Associative Arrays

# Declare associative array
declare -A user_info

# Initialize with values
user_info=(
    ["name"]="John Doe"
    ["email"]="[email protected]"
    ["age"]="30"
)

# Add elements individually
declare -A server_config
server_config["hostname"]="webserver01"
server_config["ip"]="192.168.1.100"
server_config["port"]="8080"

Working with Associative Arrays

# Access elements
echo ${user_info["name"]}  # John Doe

# Get all keys
echo ${!user_info[@]}  # name email age

# Get all values
echo ${user_info[@]}  # John Doe [email protected] 30

# Check if key exists
if [[ -v user_info["email"] ]]; then
    echo "Email exists: ${user_info["email"]}"
fi

Advanced Array Techniques

Looping Through Arrays

# Loop through indexed array
echo "Fruits in basket:"
for fruit in "${fruits[@]}"; do
    echo "- $fruit"
done

# Loop with index
echo "Fruits with index:"
for i in "${!fruits[@]}"; do
    echo "$i: ${fruits[$i]}"
done

# Loop through associative array
echo "User Information:"
for key in "${!user_info[@]}"; do
    echo "$key: ${user_info[$key]}"
done

Array Functions

#!/bin/bash

# Function to print array
print_array() {
    local -n arr=$1
    echo "Array contents:"
    for element in "${arr[@]}"; do
        echo "  - $element"
    done
}

# Function to find element in array
array_contains() {
    local -n arr=$1
    local search=$2
    
    for element in "${arr[@]}"; do
        if [[ "$element" == "$search" ]]; then
            return 0
        fi
    done
    return 1
}

# Usage
my_array=("red" "green" "blue")
print_array my_array

if array_contains my_array "green"; then
    echo "Found green in array"
fi

Array Manipulation

# Reverse an array
reverse_array() {
    local -n arr=$1
    local -a reversed=()
    
    for ((i=${#arr[@]}-1; i>=0; i--)); do
        reversed+=("${arr[$i]}")
    done
    
    arr=("${reversed[@]}")
}

# Sort array
sort_array() {
    local -n arr=$1
    IFS=$'\n' arr=($(sort <<<"${arr[*]}"))
    unset IFS
}

# Remove duplicates
unique_array() {
    local -n arr=$1
    local -A seen=()
    local -a unique=()
    
    for element in "${arr[@]}"; do
        if [[ ! -v seen["$element"] ]]; then
            seen["$element"]=1
            unique+=("$element")
        fi
    done
    
    arr=("${unique[@]}")
}

Practical Examples

Example 1: File Processing

#!/bin/bash

# Process files in directory
declare -a text_files
declare -A file_info

# Find all text files
text_files=($(find . -name "*.txt" -type f))

echo "Found ${#text_files[@]} text files"

# Gather file information
for file in "${text_files[@]}"; do
    size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file")
    lines=$(wc -l < "$file")
    
    file_info["$file,size"]=$size
    file_info["$file,lines"]=$lines
done

# Display file information
for file in "${text_files[@]}"; do
    echo "File: $file"
    echo "  Size: ${file_info["$file,size"]} bytes"
    echo "  Lines: ${file_info["$file,lines"]}"
done

Example 2: Configuration Parser

#!/bin/bash

# Parse configuration file into associative array
declare -A config

parse_config() {
    local config_file=$1
    
    while IFS='=' read -r key value; do
        # Skip comments and empty lines
        [[ "$key" =~ ^[[:space:]]*# ]] && continue
        [[ -z "$key" ]] && continue
        
        # Trim whitespace
        key=$(echo "$key" | xargs)
        value=$(echo "$value" | xargs)
        
        config["$key"]="$value"
    done < "$config_file"
}

# Usage
parse_config "/etc/myapp.conf"

# Access configuration
echo "Database host: ${config[db_host]}"
echo "Database port: ${config[db_port]}"

Example 3: Menu System

#!/bin/bash

# Create menu using arrays
declare -a menu_options=(
    "System Information"
    "Disk Usage"
    "Network Status"
    "Process List"
    "Exit"
)

declare -A menu_actions=(
    ["System Information"]="uname -a"
    ["Disk Usage"]="df -h"
    ["Network Status"]="ip addr show"
    ["Process List"]="ps aux | head -20"
    ["Exit"]="exit 0"
)

show_menu() {
    echo "===== System Admin Menu ====="
    for i in "${!menu_options[@]}"; do
        echo "$((i+1)). ${menu_options[$i]}"
    done
    echo "=========================="
}

# Main loop
while true; do
    show_menu
    read -p "Select option: " choice
    
    if [[ $choice -ge 1 && $choice -le ${#menu_options[@]} ]]; then
        selected="${menu_options[$((choice-1))]}"
        echo -e "\nExecuting: $selected\n"
        eval "${menu_actions[$selected]}"
        echo -e "\nPress Enter to continue..."
        read
    else
        echo "Invalid option"
    fi
done

Example 4: Data Processing

#!/bin/bash

# Process CSV data with arrays
declare -a headers
declare -a data_rows

read_csv() {
    local csv_file=$1
    local line_num=0
    
    while IFS=',' read -r -a row; do
        if [[ $line_num -eq 0 ]]; then
            headers=("${row[@]}")
        else
            data_rows+=("${row[*]}")
        fi
        ((line_num++))
    done < "$csv_file"
}

# Calculate column statistics
calculate_stats() {
    local column_idx=$1
    local -a values=()
    
    for row in "${data_rows[@]}"; do
        IFS=',' read -r -a fields <<< "$row"
        values+=("${fields[$column_idx]}")
    done
    
    # Calculate sum (assuming numeric values)
    local sum=0
    for val in "${values[@]}"; do
        sum=$((sum + val))
    done
    
    echo "Column: ${headers[$column_idx]}"
    echo "Sum: $sum"
    echo "Count: ${#values[@]}"
    echo "Average: $((sum / ${#values[@]}))"
}

Array Best Practices

1. Quote Array Expansions

# Good - preserves spaces and special characters
for item in "${array[@]}"; do
    echo "$item"
done

# Bad - word splitting issues
for item in ${array[@]}; do
    echo $item
done

2. Check Array Bounds

# Safe array access
safe_get() {
    local -n arr=$1
    local index=$2
    
    if [[ $index -ge 0 && $index -lt ${#arr[@]} ]]; then
        echo "${arr[$index]}"
    else
        echo "Index out of bounds" >&2
        return 1
    fi
}

3. Use Local Arrays in Functions

process_data() {
    local -a temp_array=()
    local -A cache=()
    
    # Process data locally
    temp_array+=("processed")
}

4. Array Serialization

# Save array to file
save_array() {
    local -n arr=$1
    local file=$2
    
    printf '%s\n' "${arr[@]}" > "$file"
}

# Load array from file
load_array() {
    local -n arr=$1
    local file=$2
    
    mapfile -t arr < "$file"
}

Common Pitfalls and Solutions

Pitfall 1: Sparse Arrays

# Creating sparse array
arr[5]="five"
arr[10]="ten"

# Problem: length is not what you expect
echo ${#arr[@]}  # 2, not 11

# Solution: Use continuous indices or associative arrays

Pitfall 2: Word Splitting

# Problem
files="file 1.txt file 2.txt"
arr=($files)  # Creates 4 elements!

# Solution
IFS=$'\n' arr=($(ls))  # Split on newlines
# Or use mapfile
mapfile -t arr < <(ls)

Pitfall 3: Passing Arrays to Functions

# Problem - only first element passed
my_func "${array[@]}"

# Solution - use nameref
my_func() {
    local -n arr=$1
    # Now arr references the original array
}
my_func array

Performance Tips

  1. Preallocate Size: For large arrays, consider preallocating
  2. Use Builtin Commands: Prefer bash builtins over external commands
  3. Avoid Repeated Lookups: Cache array lengths and frequently accessed elements
  4. Use Associative Arrays: For key-based lookups instead of searching

Conclusion

Bash arrays are versatile tools for script development. Whether you’re processing files, managing configurations, or building interactive scripts, arrays provide the flexibility you need.

Key takeaways:

  • Use indexed arrays for ordered data
  • Use associative arrays for key-value pairs
  • Always quote array expansions
  • Consider performance for large datasets
  • Test edge cases with empty and sparse arrays

Master these array techniques to write more efficient and maintainable Bash scripts! 🎯