Bash String Manipulation: Substring, Replace, Split and More

March 17, 2026

Bash String Manipulation: Substring, Replace, Split and More

March 17, 2026

Bash string manipulation uses parameter expansion — a built-in syntax that handles most string operations without any external commands. Understanding ${var#prefix}, ${var//old/new}, and ${var:pos:len} will let you slice, replace, and transform strings entirely within Bash, making your scripts faster and more portable. This guide covers every essential bash string operation with concrete examples.

Operation Syntax Length ${#var} Substring ${var:pos:len} Replace first ${var/old/new} Replace all ${var//old/new} Uppercase ${var^^} Strip prefix ${var#prefix} Strip suffix ${var%suffix}
Quick reference for the most-used bash string manipulation operations

1. String Length and Substring Extraction

bash
str="Hello, World!"

# String length
echo "${#str}"          # 13

# Substring: start at position 7, take 5 characters
echo "${str:7:5}"       # World

# Start at position 7, take everything to the end
echo "${str:7}"         # World!

# Negative position: start 6 chars from the end
echo "${str: -6}"       # World!   (note the space before -)

# Negative position + length
echo "${str: -6:5}"     # World

# Extract filename without extension
filename="report.tar.gz"
echo "${filename%.*}"   # report.tar  (removes last .gz)
echo "${filename%%.*}"  # report      (removes from first dot)

For negative positions, a space before the minus sign is required: ${str: -6}. Without the space, Bash interprets it as the default-value syntax ${str:-default}.

2. Find and Replace

bash
str="the cat sat on the mat"

# Replace FIRST occurrence
echo "${str/the/a}"       # a cat sat on the mat

# Replace ALL occurrences (double slash)
echo "${str//the/a}"      # a cat sat on a mat

# Delete a substring (replace with nothing)
echo "${str// /}"         # thecatsatonthemat  (remove all spaces)

# Replace using a glob pattern
path="/usr/local/bin/script.sh"
echo "${path/\/usr\/local/~}"    # ~/bin/script.sh

# Case-insensitive replace requires a workaround (use sed for this)
echo "$str" | sed 's/The/a/gi'   # handles case-insensitive

3. Case Conversion

Bash 4+ supports built-in case conversion operators:

bash
name="hello world"

echo "${name^^}"    # HELLO WORLD  (all uppercase)
echo "${name,,}"    # hello world  (all lowercase)
echo "${name^}"     # Hello world  (capitalize first char)
echo "${name,}"     # hello world  (lowercase first char)

# Uppercase only certain chars (^[aeiou] = capitalize vowels)
echo "${name^^[aeiou]}"   # hEllO wOrld

4. Stripping Prefixes and Suffixes

The # and % operators strip matched patterns from the start or end of a string. Use one symbol for shortest match, two for longest:

path="/home/user/documents/report.pdf"

# Strip prefix (from the LEFT)
echo "${path#*/}"       # home/user/documents/report.pdf  (strips up to first /)
echo "${path##*/}"      # report.pdf  (strips up to LAST / — greedy)

# Strip suffix (from the RIGHT)
echo "${path%.*}"       # /home/user/documents/report  (strips .pdf)
echo "${path%%.*}"      # /home/user/documents/report  (same here, but watch out with multiple dots)

# Practical: get just the filename
filename="${path##*/}"
echo "$filename"        # report.pdf

# Practical: get directory path
dir="${path%/*}"
echo "$dir"             # /home/user/documents

# Practical: get extension
ext="${filename##*.}"
echo "$ext"             # pdf

5. Splitting Strings

csv="apple,banana,cherry"

# Split on comma using IFS
IFS=',' read -ra parts <<< "$csv"
echo "${parts[0]}"   # apple
echo "${parts[1]}"   # banana
echo "${parts[2]}"   # cherry

# Loop over parts
for part in "${parts[@]}"; do
    echo "Part: $part"
done

# Split a colon-delimited path
IFS=':' read -ra dirs <<< "$PATH"
for dir in "${dirs[@]}"; do
    echo "$dir"
done

6. Trim Whitespace

str="   hello world   "

# Trim with xargs (trims both ends)
trimmed=$(echo "$str" | xargs)
echo "$trimmed"   # hello world

# Trim with parameter expansion (leading spaces)
str="${str#"${str%%[![:space:]]*}"}"

# Trim with sed
trimmed=$(echo "$str" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
echo "$trimmed"   # hello world

For bulk find-and-replace across files, the bash sed command guide covers this in depth. For checking whether a string contains a substring, see the bash case statement guide which uses pattern matching.

Summary

Bash parameter expansion handles all common string operations without forking external processes. The key patterns: ${#var} for length, ${var:pos:len} for substrings, ${var//old/new} for global replace, ${var^^}/${var,,} for case, and ${var##*/}/${var%.*} for path/extension manipulation.