How can I improve this? I added the while read
loop to handle preceding newlines.
trim()
{
# skip leading whitespace
while read -r string; do [[ -n "${string}" ]] && break; done
string="${string#"${string%%[![:space:]]*}"}"
string="${string%"${string##*[![:space:]]}"}"
printf "${string}"
}
Usage:
$ echo " hello " | trim; echo
hello
$ echo "
hello multi-line
" | trim
hello multi-line
$
1 Answer 1
The comment is misleading - the function does skip leading whitespace-only lines, but it also removes all lines after the first non-whitespace.
I would simplify to read all of the input into string
, and then remove the whitespace:
string=$(cat)
string="${string#"${string%%[![:space:]]*}"}"
Don't make the result the format-string for printf
- any % in the input will be substituted (e.g. trim <<<%d
results in 0
as output). Instead, use %s
as the format string:
printf %s "$string"
Modified code
trim()
{
string=$(cat)
string=${string#${string%%[![:space:]]*}}
printf %s "${string%${string##*[![:space:]]}}"
}
And some improved tests:
tests=(
' hello '
'
hello multi-line ''
'
'
two
lines
'
'%d'
' '
'
'
)
for s in "${tests[@]}"
do
printf '%s\n^%s$\n\n' "${s@Q}" "$(trim <<<"$s")"
done