Site Tools


wiki:shell-advanced-features

Shell Advanced Features

Indexed Arrays

Arrays store multiple values in a single variable. Declare with arr=(val1 val2 val3) or assign individual elements.

# Declare array
colors=("red" "green" "blue")
 
# Access by index (zero-based)
echo ${colors[0]}    # Output: red
echo ${colors[2]}    # Output: blue
 
# Assign individual elements
colors[3]="yellow"
 
# Get all elements
echo ${colors[@]}    # Output: red green blue yellow
 
# Get array length
echo ${#colors[@]}   # Output: 4
 
# Iterate over array
for color in "${colors[@]}"; do
    echo "$color"
done

Use associative arrays (hash maps) with declare -A for key-value pairs:

# Declare associative array
declare -A config
config[host]="localhost"
config[port]="8080"
config[user]="admin"
 
# Access by key
echo ${config[host]}   # Output: localhost
 
# Iterate over keys and values
for key in "${!config[@]}"; do
    echo "$key = ${config[$key]}"
done

Here Documents

Pass multi-line text to stdin using <<DELIMITER ... DELIMITER. Useful for embedding SQL, config files, or heredocs.

# Basic here document
cat << EOF
This is line 1
This is line 2
Variables work: $HOME
EOF
 
# Pipe into a command
mysql -u root -p << SQL
CREATE TABLE users (id INT, name VARCHAR(50));
INSERT INTO users VALUES (1, 'Alice');
SQL
 
# Suppress leading tabs with <<-
cat <<- EOF
    Indented text
    Tab indentation is stripped
EOF

Quote the delimiter to disable variable expansion:

# Variables expanded
cat << EOF
$HOME is your home directory
EOF
 
# Variables not expanded (literal dollar signs)
cat << 'EOF'
$HOME is shown literally
${VAR} is not expanded
EOF

Pattern Matching and Globbing

Use [[ $var == pattern ]] for pattern matching in conditionals. Bash supports glob patterns and extended globs.

# Basic pattern matching
file="document.pdf"
[[ $file == *.pdf ]] && echo "PDF file"
 
# Match any single character with ?
filename="file1.txt"
[[ $filename == file?.txt ]] && echo "Matches file1.txt, file2.txt, etc."
 
# Match character sets with [...]
[[ "test" == [a-z]* ]] && echo "Starts with lowercase"
[[ "123" == [0-9]* ]] && echo "Starts with digit"

Enable extended glob patterns with shopt -s extglob for more powerful matching:

shopt -s extglob
 
# ?(pattern) - zero or one occurrence
[[ "hello" == ?(hel)lo ]] && echo "Matches"
 
# *(pattern) - zero or more occurrences
[[ "aaab" == *(a)b ]] && echo "Matches"
 
# +(pattern) - one or more occurrences
[[ "aaab" == +(a)b ]] && echo "Matches"
 
# !(pattern) - anything except pattern
[[ "test" == !(abc)* ]] && echo "Does not start with abc"

String Manipulation

Bash provides parameter expansion for substring extraction, replacement, and trimming.

filename="document.pdf"
 
# Substring: ${var:offset:length}
echo ${filename:0:8}      # Output: document
 
# Remove extension: ${var%pattern}
echo ${filename%.pdf}     # Output: document
 
# Remove prefix: ${var#pattern}
path="/home/user/file.txt"
echo ${path#/home/}       # Output: user/file.txt
 
# Replace first occurrence: ${var/old/new}
text="hello hello"
echo ${text/hello/hi}     # Output: hi hello
 
# Replace all occurrences: ${var//old/new}
echo ${text//hello/hi}    # Output: hi hi
 
# Default value if unset: ${var:-default}
echo ${UNDEFINED:-"no value"}  # Output: no value

Combine operations for powerful string processing:

# Extract filename without extension from a path
path="/home/user/documents/report.pdf"
name=${path##*/}          # Get filename only: report.pdf
base=${name%.*}           # Remove extension: report
 
# Uppercase (bash 4+)
str="hello"
echo ${str^^}             # Output: HELLO
 
# Lowercase
echo ${str,,}             # Output: hello
wiki/shell-advanced-features.md · Last modified: by 127.0.0.1