Parameter_expansion
Chapter 28: Parameter Expansion in Bash
Section titled “Chapter 28: Parameter Expansion in Bash”Overview
Section titled “Overview”Parameter expansion is a powerful feature that allows you to manipulate variable values in sophisticated ways without calling external commands. This chapter covers all parameter expansion techniques essential for efficient bash scripting.
What is Parameter Expansion?
Section titled “What is Parameter Expansion?”Parameter expansion is the mechanism by which the shell replaces a parameter (variable) with its value. It goes far beyond simple $variable substitution.
┌────────────────────────────────────────────────────────────────┐│ Parameter Expansion Types │├────────────────────────────────────────────────────────────────┤│ ││ Basic: ││ ────── ││ $VAR → value ││ ${VAR} → value ││ ││ Default Values: ││ ───────────── ││ ${VAR:-value} → value if unset/null ││ ${VAR:=value} → assign if unset/null ││ ${VAR:+value} → alt value if set ││ ${VAR:?message} → error if unset/null ││ ││ String Operations: ││ ─────────────── ││ ${#VAR} → length ││ ${VAR:offset} → substring from offset ││ ${VAR:offset:len} → substring ││ ││ Pattern Removal: ││ ─────────────── ││ ${VAR#pattern} → remove shortest prefix ││ ${VAR##pattern} → remove longest prefix ││ ${VAR%pattern} → remove shortest suffix ││ ${VAR%%pattern} → remove longest suffix ││ ││ Pattern Replacement: ││ ────────────────── ││ ${VAR/pattern/string} → replace first ││ ${VAR//pattern/string} → replace all ││ ${VAR/#pattern/string} → replace prefix ││ ${VAR/%pattern/string} → replace suffix ││ │└────────────────────────────────────────────────────────────────┘Basic Parameter Expansion
Section titled “Basic Parameter Expansion”Simple Expansion
Section titled “Simple Expansion”# Basic variablename="Alice"echo $nameecho ${name}
# In stringsecho "Hello, $name"echo "Hello, ${name}"Default Values
Section titled “Default Values”Use Default If Unset
Section titled “Use Default If Unset”# ${parameter:-default}# Returns default if parameter is unset or null
unset var1var2=""
echo "${var1:-default}" # default (var1 is unset)echo "${var2:-default}" # default (var2 is null)echo "${var3:-default}" # default (var3 never set)
# Common useecho "${CONFIG_FILE:-/etc/default.conf}"Assign Default If Unset
Section titled “Assign Default If Unset”# ${parameter:=default}# Assigns default if parameter is unset or null
unset var1echo "${var1:=assigned}" # assigned, var1 now has value
var2=""echo "${var2:=assigned}" # assigned, var2 now has value
# Common use: "${DATABASE_HOST:=localhost}"# : is a no-op, but expansion happensAlternate Value If Set
Section titled “Alternate Value If Set”# ${parameter:+alternate}# Returns alternate if parameter is set and non-null
var1="value"var2=""
echo "${var1:+alternate}" # alternate (var1 is set)echo "${var2:+alternate}" # empty (var2 is null)echo "${var3:+alternate}" # empty (var3 is unset)
# Practical useDEBUG_MODE=1echo "${DEBUG_MODE:+--debug-flag}" # --debug-flag if setError If Unset
Section titled “Error If Unset”# ${parameter:?message}# Errors out if parameter is unset or null
unset important_var
# This will print error and exit# echo "${important_var:?Error: Variable not set}"
# More specific message# echo "${important_var:?Please set the important_var variable}"
# Practical use in scripts: "${DATABASE_URL:?Error: DATABASE_URL must be set}"String Length
Section titled “String Length”Get Variable Length
Section titled “Get Variable Length”# ${#parameter}
name="Hello"echo ${#name} # 5
path="/home/user/documents"echo ${#path} # 22
# Array length (first element)arr=(one two three)echo ${#arr} # 3 (length of first element)
# Array length (all elements)echo ${#arr[@]} # 3Substring Operations
Section titled “Substring Operations”Extract Substring
Section titled “Extract Substring”# ${parameter:offset}# ${parameter:offset:length}
text="Hello World"
# From offset (0-based)echo "${text:6}" # World (from position 6)
# With lengthecho "${text:0:5}" # Hello (first 5 chars)echo "${text:6:5}" # World (5 chars from position 6)
# Negative offset (from end)echo "${text:-6}" # Hello World (treats -6 as literal with :-)echo "${text: -5}" # World (space before -5 is required)echo "${text: -5:2}" # WoPattern Removal
Section titled “Pattern Removal”Remove Pattern from Beginning
Section titled “Remove Pattern from Beginning”# ${parameter#pattern} - shortest match# ${parameter##pattern} - longest match
path="/home/user/documents/file.txt"
# Remove shortest matchecho "${path#*/}" # home/user/documents/file.txt (until /)
# Remove longest matchecho "${path##*/}" # file.txt (last /)
# With patternsfilename="/var/log/nginx/access.log"echo "${filename##*/}" # access.logRemove Pattern from End
Section titled “Remove Pattern from End”# ${parameter%pattern} - shortest match# ${parameter%%pattern} - longest match
path="/home/user/documents/file.txt"
# Remove shortest matchecho "${path%/*}" # /home/user/documents (after last /)
# Remove longest matchecho "${path%%/*}" # (first /)
# Extension removalfilename="document.tar.gz"echo "${filename%.*}" # document.tarecho "${filename%%.*}" # documentPattern Replacement
Section titled “Pattern Replacement”Replace First Match
Section titled “Replace First Match”# ${parameter/pattern/string}
text="hello world hello"
# Replace first occurrenceecho "${text/hello/bye}" # bye world hello
# Case insensitiveecho "${text//[Hh]ello/bye}" # bye world bye
# If string is emptyecho "${text/pattern/}" # Removes first matchecho "${text//pattern/}" # Removes all matchesReplace All Matches
Section titled “Replace All Matches”# ${parameter//pattern/string}
text="hello world hello"
echo "${text//hello/bye}" # bye world byeecho "${text//l/_}" # he__o wor__d he__oReplace Prefix
Section titled “Replace Prefix”# ${parameter/#pattern/string}
filename="prefix_file.txt"echo "${filename/#prefix_/}" # file.txt
url="https://example.com"echo "${url#https://}" # example.comReplace Suffix
Section titled “Replace Suffix”# ${parameter/%pattern/string}
filename="document.txt"echo "${filename%.txt}" # document
url="example.com/index.html"echo "${url%.html}" # example.com/indexArrays and Parameter Expansion
Section titled “Arrays and Parameter Expansion”Array Length
Section titled “Array Length”# Arrayarr=(one two three four)
echo ${#arr} # 3 (length of first element)echo ${#arr[@]} # 4 (number of elements)echo ${#arr[*]} # 4Array Slicing
Section titled “Array Slicing”arr=(a b c d e f)
# All elements from indexecho ${arr[@]:2} # c d e f
# Elements from index with countecho ${arr[@]:2:2} # c dArray Element Removal
Section titled “Array Element Removal”arr=(one two three two four)
# Remove first matching elementunset 'arr[1]' # Remove element at index 1arr=( "${arr[@]/two}" ) # Remove by value
# Remove all matchingarr=( "${arr[@]//two}" )Special Parameters
Section titled “Special Parameters”Positional Parameters
Section titled “Positional Parameters”#!/bin/bash# $0, $1, $2, etc.
echo $0 # Script nameecho $1 # First argumentecho $2 # Second argumentecho $# # Number of argumentsecho $@ # All argumentsecho $* # All arguments (single string)
# Shiftshift # $2 becomes $1shift 2 # Shift by 2Special Variables
Section titled “Special Variables”echo $$ # Current PIDecho $! # PID of last background jobecho $? # Exit status of last commandecho $! # PID of last background processPractical DevOps Examples
Section titled “Practical DevOps Examples”Path Manipulation
Section titled “Path Manipulation”#!/usr/bin/env bash
# Get filename from pathfilepath="/var/log/nginx/access.log"filename="${filepath##*/}" # access.log
# Get directory from pathdir="${filepath%/*}" # /var/log/nginx
# Get extensionext="${filename##*.}" # log
# Base name without extensionbase="${filename%.*}" # accessConfiguration with Defaults
Section titled “Configuration with Defaults”#!/usr/bin/env bash# Application configuration with sensible defaults
export APP_NAME="${APP_NAME:-myapp}"export APP_ENV="${APP_ENV:-production}"export APP_PORT="${APP_PORT:-8080}"export LOG_LEVEL="${LOG_LEVEL:-info}"export MAX_CONNECTIONS="${MAX_CONNECTIONS:-100}"export TIMEOUT_SECONDS="${TIMEOUT_SECONDS:-30}"
echo "Starting $APP_NAME in $APP_ENV mode"echo "Port: $APP_PORT, Log: $LOG_LEVEL"Input Validation
Section titled “Input Validation”#!/usr/bin/env bash
validate_required() { local var_name="$1" local var_value="${!var_name}" # Indirect expansion
if [[ -z "$var_value" ]]; then echo "Error: $var_name is required but not set" return 1 fi}
# UsageDATABASE_URL="postgres://localhost/db"validate_required "DATABASE_URL"String Manipulation
Section titled “String Manipulation”#!/usr/bin/env bash
# Convert to lowercasetext="HELLO WORLD"echo "${text,,}" # hello world
# Convert to uppercasetext="hello world"echo "${text^^}" # HELLO WORLD
# Replace patternsconfig="DEBUG=true"echo "${config,,}" # debug=true
# Remove quotesvalue='"quoted string"'echo "${value//\"}" # quoted stringUsername from Email
Section titled “Username from Email”#!/usr/bin/env bash
email="john.doe@example.com"
# Get username (before @)username="${email%%@*}" # john.doe
# Get domain (after @)domain="${email#*@}" # example.comAdvanced Techniques
Section titled “Advanced Techniques”Indirect Expansion
Section titled “Indirect Expansion”var1="value1"var_name="var1"
# Get value by nameecho "${!var_name}" # value1
# For arraysarr=(one two three)i=0echo "${!arr[$i]}" # one (element at index 0)Case Modification
Section titled “Case Modification”# Bash 4+
text="Hello World"
# Lowercaseecho "${text,,}" # hello world
# Uppercaseecho "${text^^}" # HELLO WORLD
# Lowercase first charecho "${text,}" # hello World
# Uppercase first charecho "${text^}" # Hello WorldDevOps-Specific Examples
Section titled “DevOps-Specific Examples”#!/usr/bin/env bash
# Parse Kubernetes resource nameresource="deployment/myapp-5d9f7b8-x"name="${resource##*/}" # myapp-5d9f7b8-xdeployment="${resource%%/*}" # deployment
# Docker image tagimage="registry.example.com/app:v1.2.3"registry="${image%%/*}" # registry.example.com/apptag="${image##*:}" # v1.2.3name="${image%:*}" # registry.example.com/app
# Semver comparisonversion="v1.2.3"major="${version%%.*}" # v1minor="${version#*.}" # 2.3minor="${minor%%.*}" # 2patch="${version##*.}" # 3Summary
Section titled “Summary”In this chapter, you learned:
- ✅ Basic parameter expansion
- ✅ Default value operators (:-), (:=), (:+), (:?)
- ✅ String length with # operator
- ✅ Substring extraction
- ✅ Pattern removal (#, ##, %, %%)
- ✅ Pattern replacement (/, //, #/, %/)
- ✅ Arrays and parameter expansion
- ✅ Special parameters (positional, $, ?, !)
- ✅ Practical DevOps examples
- ✅ Advanced techniques (indirect expansion, case modification)
Next Steps
Section titled “Next Steps”Continue to the next chapter to learn about Command Substitution.
Previous Chapter: Shell Expansion Next Chapter: Command Substitution