Linux Basics: Transform Text with Bash Parameter Expansion
Bash can supply defaults and reshape strings without launching another program. Parameter expansion is especially handy for small, predictable pieces of text inside a script.
These examples were tested on Linux with GNU Bash 5.2.37. Use Bash rather than sh; some syntax is Bash-specific. No packages or administrator access are needed.
Prepare a scratch directory
You need Bash, a text editor, and the mktemp, rm, and rmdir utilities. Keep using the same terminal. The guards stop the shell if setup fails. Save each named source file in this directory before running its command. Calling bash explicitly means you do not need to change executable permissions.
start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 11. Choose defaults for missing text
Save this as expansion-defaults.sh:
#!/usr/bin/env bash
unset nickname
printf 'Unset: %s\n' "${nickname:-guest}"
nickname=''
printf 'Empty with colon: %s\n' "${nickname:-guest}"
printf 'Empty without colon: <%s>\n' "${nickname-guest}"
printf 'Still empty: <%s>\n' "$nickname"Run it:
bash expansion-defaults.shOutput:
Unset: guest
Empty with colon: guest
Empty without colon: <>
Still empty: <>:- substitutes a fallback when a variable is unset or empty. - substitutes only when it is unset. Neither assigns the fallback to the variable. Quoting the complete expansion preserves the resulting text as one argument.
2. Remove a path prefix and suffix
Save this as expansion-paths.sh:
#!/usr/bin/env bash
path='reports/monthly.summary.csv'
filename=${path##*/}
stem=${filename%.*}
printf 'Filename: %s\n' "$filename"
printf 'Stem: %s\n' "$stem"
printf 'First-dot stem: %s\n' "${filename%%.*}"Run it:
bash expansion-paths.shOutput:
Filename: monthly.summary.csv
Stem: monthly.summary
First-dot stem: monthly## removes the longest matching prefix, while % removes the shortest matching suffix and %% the longest. These use shell patterns, not regular expressions. Here the last slash and last dot delimit useful parts of a known filename. This is text processing only: it does not check whether the path exists or cover every naming convention.
3. Replace text and take a slice
Save this as expansion-text.sh:
#!/usr/bin/env bash
title='weekly status update'
printf 'First replacement: %s\n' "${title/ /-}"
printf 'All replacements: %s\n' "${title// /-}"
printf 'Length: %s\n' "${#title}"
printf 'Slice: %s\n' "${title:7:6}"Run it:
bash expansion-text.shOutput:
First replacement: weekly-status update
All replacements: weekly-status-update
Length: 20
Slice: statusA single slash replaces the first match; two replace every match. The pattern here is one literal space. ${#title} gives the string length and ${title:7:6} takes six characters starting at zero-based offset seven. This example uses ASCII so the output is independent of multibyte character handling.
Clean up
In the same terminal, remove only the example files, return to your original directory, and remove the empty scratch directory:
rm -- expansion-defaults.sh expansion-paths.sh expansion-text.sh
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dirReference
The GNU Bash manual: Shell Parameter Expansion documents the syntax used here.
Acknowledgements
This post was created with assistance from AI.