Neural Sync Active
Advanced Shell Scripting
Registry Synced
Advanced Shell Scripting
1025 words
5 min read
Reading compass
Now · 🎯 Learning Objectives
Advanced Shell Scripting
🎯 Learning Objectives
- Use arrays and associative arrays in bash
- Perform string manipulation
- Debug shell scripts effectively
- Handle errors robustly
- Parse command-line options with getopts
- Use advanced I/O and process substitution
1. Arrays and Associative Arrays
bash#!/bin/bash # Indexed arrays fruits=("apple" "banana" "cherry") fruits[3]="date" # Add element echo ${fruits[0]} # apple echo ${fruits[@]} # All elements echo ${#fruits[@]} # Length (4) echo ${!fruits[@]} # Indices (0 1 2 3) # Loop with index for i in "${!fruits[@]}"; do echo "Index $i: ${fruits[$i]}" done # Associative arrays (bash 4+) declare -A capitals capitals=([India]="New Delhi" [USA]="Washington" [UK]="London") echo ${capitals[India]} # New Delhi echo ${!capitals[@]} # All keys echo ${capitals[@]} # All values for country in "${!capitals[@]}"; do echo "$country: ${capitals[$country]}" done
2. String Manipulation
bash#!/bin/bash text="Hello World from Bash" # Length echo ${#text} # 19 # Substring echo ${text:6} # World from Bash (from index 6) echo ${text:6:5} # World (5 chars from index 6) # Pattern removal (prefix) echo ${text#Hello*} # Remove shortest "Hello*" prefix echo ${text##* } # Remove longest " *" prefix → "Bash" # Pattern removal (suffix) echo ${text% *} # Remove shortest " *" suffix → "Hello World from" echo ${text%% *} # Remove longest " *" suffix → "Hello" # Search and replace echo ${text/World/Earth} # Replace first: "Hello Earth from Bash" echo ${text// /_} # Replace all spaces: "Hello_World_from_Bash" echo ${text/#Hello/Hi} # Replace at start echo ${text/%Bash/sh} # Replace at end # Case conversion echo ${text,,} # Lowercase: "hello world from bash" echo ${text^^} # Uppercase: "HELLO WORLD FROM BASH" echo ${text,} # First char lowercase echo ${text^} # First char uppercase # Default values name=${1:-"Guest"} # Use $1 or default "Guest" file=${name:?Error: name required} # Exit with error if empty
3. Debugging Scripts
bash#!/bin/bash # Debugging methods: # 1. Shebang flags #!/bin/bash -x # Print commands and their arguments # 2. Set options in script set -x # Enable debug (print commands) set +x # Disable debug set -v # Print shell input lines as read set -n # Read commands but don't execute (syntax check) # 3. Selective debugging set -x # Start debugging # ... commands to debug ... set +x # Stop debugging # 4. Verbose debugging PS4='+ $BASH_SOURCE:$LINENO: $0: ' # Customize debug prompt set -x # 5. Check syntax without running # bash -n script.sh # Syntax check only # 6. Trace execution # bash -x script.sh # Full trace # bash -vx script.sh # Verbose + trace
4. Error Handling
bash#!/bin/bash # Strict mode set -euo pipefail # Exit on error, undefined vars, pipe fails # Custom error handler error_handler() { local line=$1 local command=$2 echo "Error on line $line: command '$command' failed" exit 1 } trap 'error_handler $LINENO "$BASH_COMMAND"' ERR # Check command success if command_not_found; then echo "Success" else echo "Failed with code: $?" fi # Retry logic max_retries=3 retry_count=0 until [ $retry_count -ge $max_retries ]; do if curl -s https://api.example.com > /dev/null; then echo "Success" break fi ((retry_count++)) echo "Retry $retry_count/$max_retries..." sleep 2 done
5. Command-Line Options with getopts
bash#!/bin/bash usage() { echo "Usage: $0 [-n name] [-a age] [-h]" exit 1 } name="" age=0 while getopts ":n:a:h" opt; do case $opt in n) name="$OPTARG" ;; a) age="$OPTARG" ;; h) usage ;; \?) echo "Invalid option: -$OPTARG" usage ;; :) echo "Option -$OPTARG requires an argument." usage ;; esac done echo "Name: $name, Age: $age" # Usage: ./script.sh -n Alice -a 25
6. Process Substitution
bash# Process substitution — feed output of command as a file # Compare two command outputs diff <(ls /dir1) <(ls /dir2) # Read from process while read line; do echo "Line: $line" done < <(grep "ERROR" log.txt) # Multiple process substitutions paste <(cut -f1 file1.txt) <(cut -f3 file2.txt)
7. Practice Questions
Q1: How do you declare an associative array in bash?Answer:declare -A myarraythenmyarray=([key1]="value1" [key2]="value2"). Associative arrays require bash 4+. Access with${myarray[key1]}. Q2: How do you remove the file extension from a filename?Answer:${filename%.*}removes the shortest suffix matching.*. Example:file="data.txt"; echo ${file%.*}→ "data". For multiple extensions:${file%%.*}removes longest suffix. Q3: What doesset -edo and why use it?Answer:set -ecauses the script to exit immediately if any command returns a non-zero exit status. Combined withset -u(error on undefined variables) andset -o pipefail(fail if any command in pipe fails), it's called "strict mode" and prevents silent failures. Q4: How do you debug a bash script?Answer:bash -x script.sh(trace mode), or addset -xin the script.bash -n script.shchecks syntax without executing.PS4='$LINENO: 'customizes the debug prompt to show line numbers. Q5: How do you parse command-line flags with getopts?Answer:bashwhile getopts ":n:a:" opt; do case $opt in n) name="$OPTARG" ;; a) age="$OPTARG" ;; esac doneThe colon prefix (:) suppresses default error messages.$OPTARGgets the argument value. Q6: What is process substitution?Answer:<(command)treats the output of a command as a file. Useful with commands that expect file arguments:diff <(cmd1) <(cmd2). Creates a named pipe or /dev/fd entry behind the scenes. Q7: How do you convert a string to uppercase in bash?Answer:${text^^}(uppercase all),${text^}(first char uppercase),${text,,}(lowercase all). These work in bash 4+. Q8: Write a function that validates a non-empty argument and returns an error if missing.bashrequire_arg() { if [ -z "$2" ]; then echo "Error: $1 is required" exit 1 fi } require_arg "--name" "$name"
📐 Key Concepts
| Feature | Syntax | Purpose |
|---|---|---|
| Array | arr=(val1 val2) | Indexed list |
| Assoc array | declare -A arr | Key-value pairs |
| String length | ${#str} | Character count |
| Substring | ${str:start:len} | Extract part |
| Replace | ${str/old/new} | Pattern replacement |
| Debug | set -x | Trace execution |
| Error trap | trap ... ERR | Catch errors |
| getopts | while getopts | Parse options |
| Process sub | <(cmd) | Output as file |