getopts_demo.sh

Download
bash 274 lines 7.5 KB
  1#!/usr/bin/env bash
  2set -euo pipefail
  3
  4# Getopts Demonstration
  5# Shows POSIX-compliant argument parsing with getopts
  6
  7# ============================================================================
  8# Color definitions for output
  9# ============================================================================
 10
 11readonly RED='\033[0;31m'
 12readonly GREEN='\033[0;32m'
 13readonly YELLOW='\033[1;33m'
 14readonly BLUE='\033[0;34m'
 15readonly CYAN='\033[0;36m'
 16readonly NC='\033[0m' # No Color
 17
 18# ============================================================================
 19# Default Values
 20# ============================================================================
 21
 22VERBOSE=false
 23OUTPUT_FILE=""
 24COUNT=1
 25SHOW_HELP=false
 26
 27# ============================================================================
 28# Usage Function
 29# ============================================================================
 30
 31usage() {
 32    cat << EOF
 33${BLUE}USAGE:${NC}
 34    $(basename "$0") [OPTIONS] [ARGUMENTS...]
 35
 36${BLUE}DESCRIPTION:${NC}
 37    Demonstrates POSIX getopts argument parsing.
 38    Processes options and remaining positional arguments.
 39
 40${BLUE}OPTIONS:${NC}
 41    -v              Enable verbose output
 42    -o FILE         Specify output file
 43    -n COUNT        Set count value (default: 1)
 44    -h              Show this help message
 45
 46${BLUE}EXAMPLES:${NC}
 47    $(basename "$0") -v file1 file2
 48    $(basename "$0") -o output.txt -n 5 input.txt
 49    $(basename "$0") -vn 3 -o result.log data/*
 50
 51${BLUE}EXIT CODES:${NC}
 52    0   Success
 53    1   Invalid option or missing argument
 54    2   Invalid argument value
 55
 56EOF
 57}
 58
 59# ============================================================================
 60# Argument Parsing
 61# ============================================================================
 62
 63parse_arguments() {
 64    local OPTIND OPTARG opt
 65
 66    # getopts format: "vho:n:"
 67    # - Letters without colon: flag options (no argument)
 68    # - Letters with colon: options that require an argument
 69    while getopts "vho:n:" opt; do
 70        case "$opt" in
 71            v)
 72                VERBOSE=true
 73                ;;
 74            h)
 75                SHOW_HELP=true
 76                ;;
 77            o)
 78                OUTPUT_FILE="$OPTARG"
 79                ;;
 80            n)
 81                if [[ ! "$OPTARG" =~ ^[0-9]+$ ]]; then
 82                    echo -e "${RED}Error:${NC} -n requires a numeric argument" >&2
 83                    usage
 84                    exit 2
 85                fi
 86                COUNT="$OPTARG"
 87                ;;
 88            \?)
 89                echo -e "${RED}Error:${NC} Invalid option: -$OPTARG" >&2
 90                usage
 91                exit 1
 92                ;;
 93            :)
 94                echo -e "${RED}Error:${NC} Option -$OPTARG requires an argument" >&2
 95                usage
 96                exit 1
 97                ;;
 98        esac
 99    done
100
101    # Shift processed options
102    shift $((OPTIND - 1))
103
104    # Remaining arguments are positional
105    POSITIONAL_ARGS=("$@")
106}
107
108# ============================================================================
109# Display Configuration
110# ============================================================================
111
112display_config() {
113    echo -e "${CYAN}=== Configuration ===${NC}"
114    echo
115
116    echo "Options parsed:"
117    echo "  Verbose:     $VERBOSE"
118    echo "  Output file: ${OUTPUT_FILE:-<not specified>}"
119    echo "  Count:       $COUNT"
120    echo
121
122    if [[ ${#POSITIONAL_ARGS[@]} -gt 0 ]]; then
123        echo "Positional arguments (${#POSITIONAL_ARGS[@]}):"
124        for i in "${!POSITIONAL_ARGS[@]}"; do
125            echo "  [$((i+1))] ${POSITIONAL_ARGS[$i]}"
126        done
127    else
128        echo "No positional arguments provided"
129    fi
130
131    echo
132}
133
134# ============================================================================
135# Processing Function
136# ============================================================================
137
138process_data() {
139    echo -e "${CYAN}=== Processing ===${NC}"
140    echo
141
142    # Verbose logging
143    verbose_log() {
144        if [[ "$VERBOSE" == true ]]; then
145            echo -e "${YELLOW}[VERBOSE]${NC} $*"
146        fi
147    }
148
149    verbose_log "Starting processing with count=$COUNT"
150
151    # Process each positional argument
152    if [[ ${#POSITIONAL_ARGS[@]} -gt 0 ]]; then
153        for arg in "${POSITIONAL_ARGS[@]}"; do
154            verbose_log "Processing: $arg"
155
156            for ((i=1; i<=COUNT; i++)); do
157                echo "  Processing '$arg' (iteration $i/$COUNT)"
158
159                if [[ "$VERBOSE" == true ]]; then
160                    sleep 0.1  # Small delay in verbose mode to show progress
161                fi
162            done
163        done
164    else
165        echo "  No input files to process"
166    fi
167
168    echo
169
170    # Handle output file
171    if [[ -n "$OUTPUT_FILE" ]]; then
172        verbose_log "Writing results to: $OUTPUT_FILE"
173
174        {
175            echo "# Processing Results"
176            echo "# Generated: $(date)"
177            echo "# Count: $COUNT"
178            echo
179            echo "Processed items:"
180            for arg in "${POSITIONAL_ARGS[@]}"; do
181                echo "  - $arg"
182            done
183        } > "$OUTPUT_FILE"
184
185        echo -e "${GREEN}${NC} Results written to: $OUTPUT_FILE"
186    else
187        verbose_log "No output file specified, results not saved"
188    fi
189
190    echo
191}
192
193# ============================================================================
194# Demo Examples
195# ============================================================================
196
197run_demo_examples() {
198    echo -e "${BLUE}╔════════════════════════════════════════════╗${NC}"
199    echo -e "${BLUE}║         Getopts Demo Examples              ║${NC}"
200    echo -e "${BLUE}╚════════════════════════════════════════════╝${NC}"
201    echo
202
203    local script_name
204    script_name=$(basename "$0")
205
206    echo "This script demonstrates getopts argument parsing."
207    echo
208    echo -e "${CYAN}Try these examples:${NC}"
209    echo
210    echo "1. Basic usage with verbose flag:"
211    echo "   ./$script_name -v file1.txt file2.txt"
212    echo
213    echo "2. Specify output file and count:"
214    echo "   ./$script_name -o output.log -n 3 input.txt"
215    echo
216    echo "3. Combined short options:"
217    echo "   ./$script_name -vn 5 -o result.txt data/*"
218    echo
219    echo "4. Show help:"
220    echo "   ./$script_name -h"
221    echo
222    echo "5. Test error handling (invalid option):"
223    echo "   ./$script_name -x"
224    echo
225    echo "6. Test error handling (missing argument):"
226    echo "   ./$script_name -o"
227    echo
228    echo "7. Test error handling (invalid count):"
229    echo "   ./$script_name -n abc"
230    echo
231
232    echo -e "${YELLOW}Note:${NC} Running demo with default behavior..."
233    echo
234}
235
236# ============================================================================
237# Main Execution
238# ============================================================================
239
240main() {
241    # Parse command-line arguments
242    declare -a POSITIONAL_ARGS=()
243    parse_arguments "$@"
244
245    # Show help if requested
246    if [[ "$SHOW_HELP" == true ]]; then
247        usage
248        exit 0
249    fi
250
251    # If no arguments provided, show demo examples
252    if [[ $# -eq 0 ]]; then
253        run_demo_examples
254        echo "Continuing with demo execution..."
255        echo
256
257        # Set demo values
258        VERBOSE=true
259        COUNT=2
260        POSITIONAL_ARGS=("demo_file1.txt" "demo_file2.txt" "demo_file3.txt")
261    fi
262
263    # Display parsed configuration
264    display_config
265
266    # Process data based on arguments
267    process_data
268
269    echo -e "${GREEN}=== Processing Complete ===${NC}"
270    echo
271}
272
273main "$@"