7
\$\begingroup\$

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
$
\$\endgroup\$

1 Answer 1

5
\$\begingroup\$

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
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.