Bashing out Spaces
There’s no need to use tr
, sed
and awk
to trim whitespace from variables as per these examples (NB: one of the popular options is described here – but not the most popular at the time of writing).
We’ll use OPTARG
as the variable, purely because I used it to strip spaces when parsing options in a script.
# Trim leading whitespace
OPTARG="${OPTARG#"${OPTARG%%[![:space:]]*}"}"
# Trim trailing whitespace
OPTARG="${OPTARG%"${OPTARG##*[![:space:]]}"}"
These look quite complicated, but are easier to understand with a worked example:
OPTARG=" The quick brown fox "
echo ">$OPTARG<"
# Outputs > The quick brown fox <
First what does the “internal” substitution do…
echo ">${OPTARG%%[![:space:]]*}<"
# Outputs > <
This removes the longest substring from the end of OPTARG
that is not whitespace followed by any character ([![:space:]]*
) — i.e. remove everything from the first non-whitespace character to the end; effectively leaving all the whitespace from the beginning of OPTARG
.
This whitespace prefix is then used as a pattern to remove from the front of OPTARG
:
echo ">${OPTARG#"${OPTARG%%[![:space:]]*}"}<"
# Outputs >The quick brown fox <
Trimming trailing whitespace does the opposite.
echo ">${OPTARG##*[![:space:]]}<"
# Outputs > <
This removes from OPTARG
the longest substring from the front of OPTARG
– matching the pattern any character followed by a non-whitespace character (*[![:space:]]
). I.e. remove everything except the trailing spaces.
Next these trailing spaces are used as the pattern to remove from the end of OPTARG
:
OPTARG="${OPTARG%"${OPTARG##*[![:space:]]}"}"
# Outputs > The quick brown fox<
Running both of these together trim leading and then trailing spaces:
OPTARG=" The quick brown fox "
OPTARG="${OPTARG#"${OPTARG%%[![:space:]]*}"}"
OPTARG="${OPTARG%"${OPTARG##*[![:space:]]}"}"
echo ">$OPTARG<"
# Outputs >The quick brown fox<
Fixing parsing errors
I have found that on some platforms (I forget which), removing the quotes around the internal substitution does not always work. It may be a script parsing issue, making the following not work. Keeping quotes around the internal substitution works:
OPTARG=" The quick brown fox "
OPTARG="${OPTARG#${OPTARG%%[![:space:]]*}}"
OPTARG="${OPTARG%${OPTARG##*[![:space:]]}}"
echo ">$OPTARG<"
# Might not work on all UNIX, but should output >The quick brown fox<
Both work on OSX and Linux from where I write this blog. Maybe not on AIX or a different version of bash. Could be something about POSIX compliance. If you find a UNIX platform where it doesn’t work, let me know.
Comments