Arrays
Chapter 11: Arrays
Section titled “Chapter 11: Arrays”Overview
Section titled “Overview”Arrays are fundamental data structures in bash that allow you to store and manipulate collections of values. This chapter covers indexed arrays in detail, including declaration, access, manipulation, and practical applications for DevOps workflows.
Array Basics
Section titled “Array Basics”What Are Arrays?
Section titled “What Are Arrays?”Arrays are ordered collections of elements, each accessed by an index. In bash, arrays can hold strings, numbers, or a mix of both.
┌─────────────────────────────────────────────────────────────────────┐│ BASH ARRAY STRUCTURE │└─────────────────────────────────────────────────────────────────────┘
┌───────────────────────────────────────────────────────────────────────┐│ ││ Index: 0 1 2 3 4 ││ Values: ["apple"] ["banana"] ["cherry"] ["date"] ["elderberry"] ││ ││ Array Name: fruits ││ ││ fruits[0] = "apple" ││ fruits[1] = "banana" ││ fruits[2] = "cherry" ││ fruits[3] = "date" ││ fruits[4] = "elderberry" ││ │└───────────────────────────────────────────────────────────────────────┘Declaring Arrays
Section titled “Declaring Arrays”Method 1: Direct Assignment
Section titled “Method 1: Direct Assignment”#!/usr/bin/env bash# Declare and initialize arrayfruits=("apple" "banana" "cherry")
echo "First element: ${fruits[0]}"echo "Second element: ${fruits[1]}"echo "Third element: ${fruits[2]}"Method 2: Index Assignment
Section titled “Method 2: Index Assignment”#!/usr/bin/env bash# Create array with specific indicescolors[0]="red"colors[2]="blue" # Can skip indicescolors[1]="green"
echo "${colors[@]}" # Output: red green blueMethod 3: Using declare
Section titled “Method 3: Using declare”#!/usr/bin/env bash# Declare arraydeclare -a numbers
# Add elementsnumbers[0]=1numbers[1]=2numbers[2]=3Method 4: From Command Output
Section titled “Method 4: From Command Output”#!/usr/bin/env bash# Create array from command outputfiles=($(ls -1 /etc/*.conf 2>/dev/null | head -5))
echo "Found ${#files[@]} config files"for file in "${files[@]}"; do echo " $file"doneAccessing Array Elements
Section titled “Accessing Array Elements”Basic Access
Section titled “Basic Access”#!/usr/bin/env bashfruits=("apple" "banana" "cherry" "date")
# Access single elementecho "${fruits[0]}" # appleecho "${fruits[1]}" # bananaecho "${fruits[2]}" # cherry
# Negative indexing (bash 4+)echo "${fruits[-1]}" # date (last element)echo "${fruits[-2]}" # cherry (second to last)Access All Elements
Section titled “Access All Elements”#!/usr/bin/env bashfruits=("apple" "banana" "cherry")
# All elements as separate wordsecho "${fruits[@]}" # apple banana cherry
# All elements as single wordecho "${fruits[*]}" # apple banana cherry
# With expansionecho "Fruits: ${fruits[@]}"Array Operations
Section titled “Array Operations”Getting Array Length
Section titled “Getting Array Length”#!/usr/bin/env bashfruits=("apple" "banana" "cherry")
# Length of arrayecho "${#fruits[@]}" # 3
# Length of elementecho "${#fruits[0]}" # 5 (length of "apple")Adding Elements
Section titled “Adding Elements”#!/usr/bin/env bashfruits=("apple" "banana")
# Add single elementfruits+=("cherry")
# Add multiple elementsfruits+=("date" "elderberry")
echo "${fruits[@]}"Removing Elements
Section titled “Removing Elements”#!/usr/bin/env bashfruits=("apple" "banana" "cherry")
# Remove element by indexunset fruits[1] # Removes "banana"
echo "${fruits[@]}" # apple cherry
# Remove entire array# unset fruits
# Reindex array after removalfruits=("${fruits[@]}")Array Slicing
Section titled “Array Slicing”#!/usr/bin/env bashnumbers=(1 2 3 4 5 6 7 8 9 10)
# Slice: from index 2, take 3 elementsecho "${numbers[@]:2:3}" # 3 4 5
# From index to endecho "${numbers[@]:5}" # 6 7 8 9 10
# First 3 elementsecho "${numbers[@]:0:3}" # 1 2 3Array Iteration
Section titled “Array Iteration”For Loop Over Array
Section titled “For Loop Over Array”#!/usr/bin/env bashfruits=("apple" "banana" "cherry")
# Iterate over elementsfor fruit in "${fruits[@]}"; do echo "Fruit: $fruit"done
echo "---"
# Iterate with indexfor i in "${!fruits[@]}"; do echo "Index $i: ${fruits[$i]}"doneWhile Loop
Section titled “While Loop”#!/usr/bin/env bashfruits=("apple" "banana" "cherry")
i=0while [ $i -lt ${#fruits[@]} ]; do echo "Fruit $i: ${fruits[$i]}" i=$((i + 1))donePractical Examples
Section titled “Practical Examples”Example 1: Server List Processing
Section titled “Example 1: Server List Processing”#!/usr/bin/env bash# List of serversservers=( "web01.example.com" "web02.example.com" "db01.example.com" "db02.example.com")
echo "Checking ${#servers[@]} servers..."
# Check each serverfor server in "${servers[@]}"; do if ping -c 1 -W 2 "$server" &>/dev/null; then echo "✓ $server is reachable" else echo "✗ $server is not reachable" fidoneExample 2: Configuration Arrays
Section titled “Example 2: Configuration Arrays”#!/usr/bin/env bash# Define services with their portsdeclare -A servicesservices=( ["nginx"]=80 ["postgresql"]=5432 ["redis"]=6379 ["elasticsearch"]=9200)
# List all servicesecho "Available services:"for service in "${!services[@]}"; do echo " $service on port ${services[$service]}"done
# Check if service existscheck_service() { local service="$1" if [ -n "${services[$service]:-}" ]; then echo "$service is configured on port ${services[$service]}" else echo "Service $service not found" fi}
check_service "nginx"check_service "mysql"Example 3: Command-Line Arguments as Array
Section titled “Example 3: Command-Line Arguments as Array”#!/usr/bin/env bash# Access arguments as arrayecho "Number of arguments: $#"echo "All arguments: ${@}"
# Process each argumentfor arg in "${@}"; do echo "Argument: $arg"done
# Using array sliceecho "First 3 arguments: ${@:1:3}"echo "Arguments starting from 2: ${@:2}"Example 4: File List with Filtering
Section titled “Example 4: File List with Filtering”#!/usr/bin/env bash# Get all log filesmapfile -t log_files < <(find /var/log -maxdepth 1 -name "*.log" 2>/dev/null)
echo "Found ${#log_files[@]} log files"
# Filter files larger than 1MBlarge_files=()for file in "${log_files[@]}"; do size=$(stat -c%s "$file" 2>/dev/null || echo 0) if [ $size -gt 1048576 ]; then large_files+=("$file") fidone
echo "Large files (>1MB): ${#large_files[@]}"for file in "${large_files[@]}"; do echo " $file"doneExample 5: Unique Values from Array
Section titled “Example 5: Unique Values from Array”#!/usr/bin/env bash# Array with duplicatesdata=(1 2 3 2 4 3 5 1 6)
# Get unique valuesunique=($(printf '%s\n' "${data[@]}" | sort -u | tr '\n' ' '))
echo "Original: ${data[@]}"echo "Unique: ${unique[@]}"Example 6: Array Intersection
Section titled “Example 6: Array Intersection”#!/usr/bin/env bash# Two arraysarray1=("apple" "banana" "cherry" "date")array2=("banana" "date" "elderberry" "fig")
# Find common elementscommon=()for item in "${array1[@]}"; do for item2 in "${array2[@]}"; do if [ "$item" = "$item2" ]; then common+=("$item") break fi donedone
echo "Common elements: ${common[@]}"Array Functions
Section titled “Array Functions”Passing Arrays to Functions
Section titled “Passing Arrays to Functions”#!/usr/bin/env bash# Function that accepts arrayprocess_array() { local arr=("$@") echo "Received ${#arr[@]} elements"
for item in "${arr[@]}"; do echo " Processing: $item" done}
fruits=("apple" "banana" "cherry")process_array "${fruits[@]}"Returning Arrays from Functions
Section titled “Returning Arrays from Functions”#!/usr/bin/env bash# Function that returns arrayget_servers() { local servers=("server1" "server2" "server3") echo "${servers[@]}"}
# Capture returned arraymapfile -t server_list < <(get_servers)
echo "Servers: ${server_list[@]}"Mapfile/Readarray
Section titled “Mapfile/Readarray”Using mapfile
Section titled “Using mapfile”#!/usr/bin/env bash# Read lines into arraymapfile -t lines < /etc/passwd
echo "First 5 lines:"for i in {0..4}; do echo "Line $i: ${lines[$i]}"done
# Read with delimitermapfile -t -d ':' fields < <(echo "field1:field2:field3")echo "Fields: ${fields[@]}"Associative Arrays (Preview)
Section titled “Associative Arrays (Preview)”Declaring Associative Arrays
Section titled “Declaring Associative Arrays”#!/usr/bin/env bash# Must declare before use (bash 4+)declare -A user_info
# Add key-value pairsuser_info["name"]="John Doe"user_info["email"]="john@example.com"user_info["role"]="admin"
# Access valuesecho "Name: ${user_info[name]}"echo "Email: ${user_info[email]}"
# Get all keysecho "Keys: ${!user_info[@]}"Best Practices
Section titled “Best Practices”Always Quote Array Expansions
Section titled “Always Quote Array Expansions”#!/usr/bin/env bash# WRONG - can cause word splittingfiles=(*.txt)rm ${files[@]} # Dangerous
# CORRECT - properly quotedrm "${files[@]}" # SafeUse -t with mapfile
Section titled “Use -t with mapfile”#!/usr/bin/env bash# Always use -t to remove trailing newlinesmapfile -t lines < file.txt
# Without -t, trailing newline is includedmapfile lines < file.txtSummary
Section titled “Summary”In this chapter, you learned about:
- ✅ Array declaration methods
- ✅ Accessing array elements
- ✅ Array operations (add, remove, slice)
- ✅ Array iteration
- ✅ Practical DevOps examples
- ✅ Array functions
- ✅ Mapfile/readarray
- ✅ Associative arrays preview
- ✅ Best practices
Exercises
Section titled “Exercises”Level 1: Basics
Section titled “Level 1: Basics”- Create an array of your favorite fruits and print them
- Add and remove elements from an array
- Iterate over array with index
Level 2: Intermediate
Section titled “Level 2: Intermediate”- Create a script that processes server list
- Implement a function that accepts array arguments
- Filter array elements based on condition
Level 3: Advanced
Section titled “Level 3: Advanced”- Create a unique value function for arrays
- Implement array intersection
- Build a configuration system using arrays
Next Steps
Section titled “Next Steps”Continue to the next chapter to learn about associative arrays in detail.
Previous Chapter: Loop Control Next Chapter: Associative Arrays