Working with Advanced Bash Features
1. Using Arrays
| Property | Description | Example |
|---|---|---|
| Array Declaration | Declare an array using parentheses | my_array=( "apple" "banana" "cherry" ) |
| Array Access | Access elements by index (0-based) | ${my_array[0]} returns "apple" |
| Array Length | Get the number of elements in an array | ${#my_array[@]} returns 3 |
| Array Append | Add an element to the end of an array | my_array+=( "date" ) |
| Array Slice | Extract a portion of an array | ${my_array[@]:1:2} returns "banana" and "cherry" |
Example: Array Declaration and Access
fruits=( "apple" "banana" "cherry" )
echo "First fruit: ${fruits[0]}"
echo "All fruits: ${fruits[@]}"
Example: Array Length and Append
colors=( "red" "green" "blue" )
echo "Number of colors: ${#colors[@]}"
colors+=( "yellow" )
echo "Updated colors: ${colors[@]}"
2. Using Associative Arrays
| Feature | Description | Example |
|---|---|---|
| declare -A | Declares an associative array | declare -A my_array |
| my_array[key]=value | Assigns a value to a key in the array | my_array["name"]="John" |
| echo ${my_array[key]} | Retrieves the value for a key | echo ${my_array["name"]} |
| ${!my_array[@]} | Lists all keys in the array | for key in ${!my_array[@]}; do echo $key; done |
| ${my_array[@]} | Lists all values in the array | for value in ${my_array[@]}; do echo $value; done |
| unset my_array[key] | Removes a key-value pair | unset my_array["name"] |
| unset -A my_array | Deletes the entire array | unset -A my_array |
Example: Using Associative Arrays for Configuration
declare -A config
config["database.host"]="localhost"
config["database.port"]="5432"
config["database.name"]="myapp_db"
echo "Database host: ${config["database.host"]}"
echo "Database port: ${config["database.port"]}"
echo "Database name: ${config["database.name"]}"
Note: Associative arrays are available in Bash 4.0 and later.
3. Using String Operations
| Operation | Description | Example |
|---|---|---|
| ${variable#pattern} | Remove shortest match of pattern from the beginning | filename="document.pdf"; echo "${filename#*.}" |
| ${variable##pattern} | Remove longest match of pattern from the beginning | path="/home/user/file.txt"; echo "${path##*/}" |
| ${variable%pattern} | Remove shortest match of pattern from the end | filename="document.pdf"; echo "${filename%.*}" |
| ${variable%%pattern} | Remove longest match of pattern from the end | filename="document.pdf.backup"; echo "${filename%%.*}" |
| ${variable/pattern/replacement} | Replace first occurrence of pattern with replacement | text="hello world"; echo "${text/world/universe}" |
| ${variable//pattern/replacement} | Replace all occurrences of pattern with replacement | text="hello world"; echo "${text//o/O}" |
Example: Extracting filename and extension
file="/home/user/document.pdf"
basename="${file##*/}"
extension="${basename##*.}"
filename="${basename%.*}"
echo "Full path: $file"
echo "Basename: $basename"
echo "Extension: $extension"
echo "Filename: $filename"
Example: Replacing multiple occurrences
text="one two three two four"
echo "Original: $text"
echo "Replace all 'two' with 'two-two': ${text//two/two-two}"
Note: These parameter expansions work on any variable and do not modify the original variable.
Common String Operations Summary
${var#pattern}- Remove shortest prefix match${var##pattern}- Remove longest prefix match${var%pattern}- Remove shortest suffix match${var%%pattern}- Remove longest suffix match${var/pattern/replacement}- Replace first occurrence${var//pattern/replacement}- Replace all occurrences
4. Using Arithmetic Expansion
| Feature | Description | Example |
|---|---|---|
| $(()) | Arithmetic expansion syntax for evaluating expressions | echo $((5 + 3)) # Output: 8 |
| $((...)) | Allows variable expansion and arithmetic operations | |
| Operators | Supports standard arithmetic operators (+, -, *, /, %) | |
| Variables in Expressions | Variables can be used inside arithmetic expansion | |
| Nested Expressions | Arithmetic expansion can be nested inside other expansions | |
Note: Arithmetic expansion evaluates expressions in integer context, truncating any decimal parts.
5. Implementing Signal Handling
| Signal | Description | Default Action | Usage |
|---|---|---|---|
| SIGTERM | Termination signal | Terminate process | Graceful shutdown of services |
| SIGKILL | Kill signal (cannot be caught) | Terminate process | Forcefully terminate a process |
| SIGINT | Interrupt from keyboard (Ctrl+C) | Terminate process | Allow user to interrupt a running script |
| SIGHUP | Hangup detected on controlling terminal | Terminate process | Reload configuration without restarting |
| SIGUSR1 | User-defined signal 1 | Terminate process | Custom actions (e.g., logging, reconfiguration) |
| SIGUSR2 | User-defined signal 2 | Terminate process | Custom actions (e.g., log rotation) |
Example: Catching SIGINT in Bash
#!/bin/bash
trap 'echo "Received SIGINT, exiting..."' INT
echo "Script running. Press Ctrl+C to trigger signal."
while true; do
echo "Working..."
sleep 2
done
Example: Handling SIGHUP to Reload Config
#!/bin/bash
config_file="/etc/myapp/config.conf"
reload_config() {
echo "Reloading configuration from $config_file"
# Logic to reload config here
}
trap reload_config HUP
echo "Starting app with config file: $config_file"
while true; do
echo "App is running..."
sleep 5
done
Note: The
trap command is used to specify actions to take when a signal is received. It can be used to handle signals like SIGINT, SIGHUP, or custom user-defined signals.
6. Using Process Substitution
Process substitution allows you to treat the output of a command as a file. It's useful for passing data to commands that expect file inputs.
| Feature | Description | Example |
|---|---|---|
| Process Substitution Syntax | Uses <(command) to run a command and treat its output as a file |
diff <(ls /etc) <(ls /tmp) |
| File Path | Generated temporary file path (e.g., /dev/fd/63) |
Output of echo <(ls) shows a path |
7. Creating Subshells
A subshell is a separate process that runs as a child of the current shell. Subshells are created when executing commands in parentheses () or using command substitution.
| Method | Description | Example |
|---|---|---|
| Command Substitution | Executes a command and captures its output as a string. | echo "Today is $(date)" |
| Parentheses Grouping | Runs commands in a subshell context, isolating variable changes. | (cd /tmp; echo $PWD) |
Example: Variable Scope Isolation
parent_var="original"
( parent_var="modified"; echo "Inside subshell: $parent_var" )
echo "Outside subshell: $parent_var"
Note: Changes made to variables inside a subshell do not affect the parent shell.
Key Points
- Subshells are created with
()or command substitution$(...). - Variables modified in a subshell do not persist in the parent shell.
- Useful for temporary environment changes or capturing command output.
8. Using set Options
| Option | Description | Effect |
|---|---|---|
| -e | Exit immediately if a command exits with a non-zero status | Terminates script on error |
| -u | Exit when trying to read from an unset variable | Prevents undefined variable usage |
| -o pipefail | Return the exit status of the last command that failed in a pipeline | Ensures proper error handling in pipelines |
| -x | Print commands and their arguments as they are executed | Enables debugging output |
Note: The
set -e option makes the script exit immediately if any command fails, which is useful for ensuring that errors are not silently ignored.
9. Debugging Scripts
| Option | Values | Description |
|---|---|---|
| set -x | bash -x script.sh |
Enables verbose mode, showing each command as it's executed |
| set -e | set -e |
Makes the script exit immediately if any command fails |
| set -u | set -u |
Treats unset variables as errors |
| set -o pipefail | set -o pipefail |
Makes pipelines return the exit status of the last command that failed |
Example: Using set -x to debug a script
#!/bin/bash
set -x
echo "Starting script"
ls /nonexistent
echo "Script finished"
Example: Using set -e to exit on error
#!/bin/bash
set -e
echo "Running command"
false
echo "This line will not execute"
Note: The
-x option can be useful for tracing execution but may produce verbose output in complex scripts.
Warning: Be cautious when using
set -e in complex scripts as it can cause unexpected exits in subshells or conditional blocks.
10. Using getopts for Options
| Option | Description | Example |
|---|---|---|
| -a | Accepts an argument | getopts "a:" opt |
| -b | Does not accept an argument | getopts "b" opt |
| --help | Display help message | getopts "h" opt |
Example: Basic getopts usage
#!/bin/bash
while getopts "a:bh" opt; do
case $opt in
a) arg_value="$OPTARG" ;;
b) flag_b=true ;;
h) echo "Usage: $0 -a <arg> -b" ;;
\?) echo "Invalid option: -$OPTARG" ;;
esac
done
echo "Argument value: $arg_value"
echo "Flag b set: $flag_b"
Note: The
getopts builtin is designed for POSIX-compliant scripts and supports only single-character options. For long options, consider using getopt.