How to trim whitespace from a Bash variable?

StringBashVariablesTrim

String Problem Overview


I have a shell script with this code:

var=`hg st -R "$path"`
if [ -n "$var" ]; then
    echo $var
fi

But the conditional code always executes, because hg st always prints at least one newline character.

  • Is there a simple way to strip whitespace from $var (like trim() in PHP)?

or

  • Is there a standard way of dealing with this issue?

I could use sed or AWK, but I'd like to think there is a more elegant solution to this problem.

String Solutions


Solution 1 - String

A simple answer is:

echo "   lol  " | xargs

Xargs will do the trimming for you. It's one command/program, no parameters, returns the trimmed string, easy as that!

Note: this doesn't remove all internal spaces so "foo bar" stays the same; it does NOT become "foobar". However, multiple spaces will be condensed to single spaces, so "foo bar" will become "foo bar". In addition it doesn't remove end of lines characters.

Solution 2 - String

Let's define a variable containing leading, trailing, and intermediate whitespace:

FOO=' test test test '
echo -e "FOO='${FOO}'"
# > FOO=' test test test '
echo -e "length(FOO)==${#FOO}"
# > length(FOO)==16

How to remove all whitespace (denoted by [:space:] in tr):

FOO=' test test test '
FOO_NO_WHITESPACE="$(echo -e "${FOO}" | tr -d '[:space:]')"
echo -e "FOO_NO_WHITESPACE='${FOO_NO_WHITESPACE}'"
# > FOO_NO_WHITESPACE='testtesttest'
echo -e "length(FOO_NO_WHITESPACE)==${#FOO_NO_WHITESPACE}"
# > length(FOO_NO_WHITESPACE)==12

How to remove leading whitespace only:

FOO=' test test test '
FOO_NO_LEAD_SPACE="$(echo -e "${FOO}" | sed -e 's/^[[:space:]]*//')"
echo -e "FOO_NO_LEAD_SPACE='${FOO_NO_LEAD_SPACE}'"
# > FOO_NO_LEAD_SPACE='test test test '
echo -e "length(FOO_NO_LEAD_SPACE)==${#FOO_NO_LEAD_SPACE}"
# > length(FOO_NO_LEAD_SPACE)==15

How to remove trailing whitespace only:

FOO=' test test test '
FOO_NO_TRAIL_SPACE="$(echo -e "${FOO}" | sed -e 's/[[:space:]]*$//')"
echo -e "FOO_NO_TRAIL_SPACE='${FOO_NO_TRAIL_SPACE}'"
# > FOO_NO_TRAIL_SPACE=' test test test'
echo -e "length(FOO_NO_TRAIL_SPACE)==${#FOO_NO_TRAIL_SPACE}"
# > length(FOO_NO_TRAIL_SPACE)==15

How to remove both leading and trailing spaces--chain the seds:

FOO=' test test test '
FOO_NO_EXTERNAL_SPACE="$(echo -e "${FOO}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
echo -e "FOO_NO_EXTERNAL_SPACE='${FOO_NO_EXTERNAL_SPACE}'"
# > FOO_NO_EXTERNAL_SPACE='test test test'
echo -e "length(FOO_NO_EXTERNAL_SPACE)==${#FOO_NO_EXTERNAL_SPACE}"
# > length(FOO_NO_EXTERNAL_SPACE)==14

Alternatively, if your bash supports it, you can replace echo -e "${FOO}" | sed ... with sed ... <<<${FOO}, like so (for trailing whitespace):

FOO_NO_TRAIL_SPACE="$(sed -e 's/[[:space:]]*$//' <<<${FOO})"

Solution 3 - String

There is a solution which only uses Bash built-ins called wildcards:

var="    abc    "
# remove leading whitespace characters
var="${var#"${var%%[![:space:]]*}"}"
# remove trailing whitespace characters
var="${var%"${var##*[![:space:]]}"}"   
printf '%s' "===$var==="

Here's the same wrapped in a function:

trim() {
    local var="$*"
    # remove leading whitespace characters
    var="${var#"${var%%[![:space:]]*}"}"
    # remove trailing whitespace characters
    var="${var%"${var##*[![:space:]]}"}"   
    printf '%s' "$var"
}

You pass the string to be trimmed in quoted form. e.g.:

trim "   abc   "

A nice thing about this solution is that it will work with any POSIX-compliant shell.

Reference

Solution 4 - String

Bash has a feature called parameter expansion, which, among other things, allows string replacement based on so-called patterns (patterns resemble regular expressions, but there are fundamental differences and limitations). [flussence's original line: Bash has regular expressions, but they're well-hidden:]

The following demonstrates how to remove all white space (even from the interior) from a variable value.

$ var='abc def'
$ echo "$var"
abc def
# Note: flussence's original expression was "${var/ /}", which only replaced the *first* space char., wherever it appeared.
$ echo -n "${var//[[:space:]]/}"
abcdef

Solution 5 - String

In order to remove all the spaces from the beginning and the end of a string (including end of line characters):

echo $variable | xargs echo -n

This will remove duplicate spaces also:

echo "  this string has a lot       of spaces " | xargs echo -n

Produces: 'this string has a lot of spaces'

Solution 6 - String

Strip one leading and one trailing space
trim()
{
    local trimmed="$1"

    # Strip leading space.
    trimmed="${trimmed## }"
    # Strip trailing space.
    trimmed="${trimmed%% }"

    echo "$trimmed"
}

For example:

test1="$(trim " one leading")"
test2="$(trim "one trailing ")"
test3="$(trim " one leading and one trailing ")"
echo "'$test1', '$test2', '$test3'"

Output:

'one leading', 'one trailing', 'one leading and one trailing'
Strip all leading and trailing spaces
trim()
{
    local trimmed="$1"

    # Strip leading spaces.
    while [[ $trimmed == ' '* ]]; do
       trimmed="${trimmed## }"
    done
    # Strip trailing spaces.
    while [[ $trimmed == *' ' ]]; do
        trimmed="${trimmed%% }"
    done

    echo "$trimmed"
}

For example:

test4="$(trim "  two leading")"
test5="$(trim "two trailing  ")"
test6="$(trim "  two leading and two trailing  ")"
echo "'$test4', '$test5', '$test6'"

Output:

'two leading', 'two trailing', 'two leading and two trailing'

Solution 7 - String

From Bash Guide section on globbing

To use an extglob in a parameter expansion

 #Turn on extended globbing  
shopt -s extglob  
 #Trim leading and trailing whitespace from a variable  
x=${x##+([[:space:]])}; x=${x%%+([[:space:]])}  
 #Turn off extended globbing  
shopt -u extglob  

Here's the same functionality wrapped in a function (NOTE: Need to quote input string passed to function):

trim() {
    # Determine if 'extglob' is currently on.
    local extglobWasOff=1
    shopt extglob >/dev/null && extglobWasOff=0 
    (( extglobWasOff )) && shopt -s extglob # Turn 'extglob' on, if currently turned off.
    # Trim leading and trailing whitespace
    local var=$1
    var=${var##+([[:space:]])}
    var=${var%%+([[:space:]])}
    (( extglobWasOff )) && shopt -u extglob # If 'extglob' was off before, turn it back off.
    echo -n "$var"  # Output trimmed string.
}

Usage:

string="   abc def ghi  ";
#need to quote input-string to preserve internal white-space if any
trimmed=$(trim "$string");  
echo "$trimmed";

If we alter the function to execute in a subshell, we don't have to worry about examining the current shell option for extglob, we can just set it without affecting the current shell. This simplifies the function tremendously. I also update the positional parameters "in place" so I don't even need a local variable

trim() {
    shopt -s extglob
    set -- "${1##+([[:space:]])}"
    printf "%s" "${1%%+([[:space:]])}" 
}

so:

$ s=$'\t\n \r\tfoo  '
$ shopt -u extglob
$ shopt extglob
extglob        	off
$ printf ">%q<\n" "$s" "$(trim "$s")"
>$'\t\n \r\tfoo  '<
>foo<
$ shopt extglob
extglob        	off

Solution 8 - String

You can trim simply with echo:

foo=" qsdqsd qsdqs q qs   "

# Not trimmed
echo \'$foo\'

# Trim
foo=`echo $foo`

# Trimmed
echo \'$foo\'

Solution 9 - String

I've always done it with sed

  var=`hg st -R "$path" | sed -e 's/  *$//'`

If there is a more elegant solution, I hope somebody posts it.

Solution 10 - String

With Bash's extended pattern matching features enabled (shopt -s extglob), you can use this:

{trimmed##*( )}

to remove an arbitrary amount of leading spaces.

Solution 11 - String

You can delete newlines with tr:

var=`hg st -R "$path" | tr -d '\n'`
if [ -n $var ]; then
    echo $var
done

Solution 12 - String

# Trim whitespace from both ends of specified parameter

trim () {
    read -rd '' $1 <<<"${!1}"
}

# Unit test for trim()

test_trim () {
    local foo="$1"
    trim foo
    test "$foo" = "$2"
}

test_trim hey hey &&
test_trim '  hey' hey &&
test_trim 'ho  ' ho &&
test_trim 'hey ho' 'hey ho' &&
test_trim '  hey  ho  ' 'hey  ho' &&
test_trim $'\n\n\t hey\n\t ho \t\n' $'hey\n\t ho' &&
test_trim $'\n' '' &&
test_trim '\n' '\n' &&
echo passed

Solution 13 - String

There are a lot of answers, but I still believe my just-written script is worth being mentioned because:

  • it was successfully tested in the shells bash/dash/busybox shell
  • it is extremely small
  • it doesn't depend on external commands and doesn't need to fork (->fast and low resource usage)
  • it works as expected:
  • it strips all spaces and tabs from beginning and end, but not more
  • important: it doesn't remove anything from the middle of the string (many other answers do), even newlines will remain
  • special: the "$*" joins multiple arguments using one space. if you want to trim & output only the first argument, use "$1" instead
  • if doesn't have any problems with matching file name patterns etc

The script:

trim() {
  local s2 s="$*"
  until s2="${s#[[:space:]]}"; [ "$s2" = "$s" ]; do s="$s2"; done
  until s2="${s%[[:space:]]}"; [ "$s2" = "$s" ]; do s="$s2"; done
  echo "$s"
}

Usage:

mystring="   here     is
    something    "
mystring=$(trim "$mystring")
echo ">$mystring<"

Output:

>here     is
    something<

Solution 14 - String

This is what I did and worked out perfect and so simple:

the_string="        test"
the_string=`echo $the_string`
echo "$the_string"

Output:

test

Solution 15 - String

If you have shopt -s extglob enabled, then the following is a neat solution.

This worked for me:

text="   trim my edges    "

trimmed=$text
trimmed=${trimmed##+( )} #Remove longest matching series of spaces from the front
trimmed=${trimmed%%+( )} #Remove longest matching series of spaces from the back

echo "<$trimmed>" #Adding angle braces just to make it easier to confirm that all spaces are removed

#Result
<trim my edges>

To put that on fewer lines for the same result:

text="    trim my edges    "
trimmed=${${text##+( )}%%+( )}

Solution 16 - String

# Strip leading and trailing white space (new line inclusive).
trim(){
	[[ "$1" =~ [^[:space:]](.*[^[:space:]])? ]]
	printf "%s" "$BASH_REMATCH"
}

OR

# Strip leading white space (new line inclusive).
ltrim(){
	[[ "$1" =~ [^[:space:]].* ]]
	printf "%s" "$BASH_REMATCH"
}

# Strip trailing white space (new line inclusive).
rtrim(){
	[[ "$1" =~ .*[^[:space:]] ]]
	printf "%s" "$BASH_REMATCH"
}

# Strip leading and trailing white space (new line inclusive).
trim(){
    printf "%s" "$(rtrim "$(ltrim "$1")")"
}

OR

# Strip leading and trailing specified characters.  ex: str=$(trim "$str" $'\n a')
trim(){
	if [ "$2" ]; then
		trim_chrs="$2"
	else
		trim_chrs="[:space:]"
	fi

	[[ "$1" =~ ^["$trim_chrs"]*(.*[^"$trim_chrs"])["$trim_chrs"]*$ ]]
	printf "%s" "${BASH_REMATCH[1]}"
}

OR

# Strip leading specified characters.  ex: str=$(ltrim "$str" $'\n a')
ltrim(){
	if [ "$2" ]; then
		trim_chrs="$2"
	else
		trim_chrs="[:space:]"
	fi

	[[ "$1" =~ ^["$trim_chrs"]*(.*[^"$trim_chrs"]) ]]
	printf "%s" "${BASH_REMATCH[1]}"
}

# Strip trailing specified characters.  ex: str=$(rtrim "$str" $'\n a')
rtrim(){
	if [ "$2" ]; then
		trim_chrs="$2"
	else
		trim_chrs="[:space:]"
	fi

	[[ "$1" =~ ^(.*[^"$trim_chrs"])["$trim_chrs"]*$ ]]
	printf "%s" "${BASH_REMATCH[1]}"
}

# Strip leading and trailing specified characters.  ex: str=$(trim "$str" $'\n a')
trim(){
    printf "%s" "$(rtrim "$(ltrim "$1" "$2")" "$2")"
}

OR

Building upon moskit's expr soulution...

# Strip leading and trailing white space (new line inclusive).
trim(){
	printf "%s" "`expr "$1" : "^[[:space:]]*\(.*[^[:space:]]\)[[:space:]]*$"`"
}

OR

# Strip leading white space (new line inclusive).
ltrim(){
	printf "%s" "`expr "$1" : "^[[:space:]]*\(.*[^[:space:]]\)"`"
}

# Strip trailing white space (new line inclusive).
rtrim(){
	printf "%s" "`expr "$1" : "^\(.*[^[:space:]]\)[[:space:]]*$"`"
}

# Strip leading and trailing white space (new line inclusive).
trim(){
	printf "%s" "$(rtrim "$(ltrim "$1")")"
}

Solution 17 - String

Use AWK:

echo $var | awk '{gsub(/^ +| +$/,"")}1'

Solution 18 - String

You can use old-school tr. For example, this returns the number of modified files in a git repository, whitespaces stripped.

MYVAR=`git ls-files -m|wc -l|tr -d ' '`

Solution 19 - String

I would simply use sed:

function trim
{
    echo "$1" | sed -n '1h;1!H;${;g;s/^[ \t]*//g;s/[ \t]*$//g;p;}'
}

a) Example of usage on single-line string

string='    wordA wordB  wordC   wordD    '
trimmed=$( trim "$string" )

echo "GIVEN STRING: |$string|"
echo "TRIMMED STRING: |$trimmed|"

Output:

GIVEN STRING: |    wordA wordB  wordC   wordD    |
TRIMMED STRING: |wordA wordB  wordC   wordD|

b) Example of usage on multi-line string

string='    wordA
   >wordB<
wordC    '
trimmed=$( trim "$string" )

echo -e "GIVEN STRING: |$string|\n"
echo "TRIMMED STRING: |$trimmed|"

Output:

GIVEN STRING: |    wordAA
   >wordB<
wordC    |

TRIMMED STRING: |wordAA
   >wordB<
wordC|

c) Final note:
If you don't like to use a function, for single-line string you can simply use a "easier to remember" command like:

echo "$string" | sed -e 's/^[ \t]*//' | sed -e 's/[ \t]*$//'

Example:

echo "   wordA wordB wordC   " | sed -e 's/^[ \t]*//' | sed -e 's/[ \t]*$//'

Output:

wordA wordB wordC

Using the above on multi-line strings will work as well, but please note that it will cut any trailing/leading internal multiple space as well, as GuruM noticed in the comments

string='    wordAA
    >four spaces before<
 >one space before<    '
echo "$string" | sed -e 's/^[ \t]*//' | sed -e 's/[ \t]*$//'

Output:

wordAA
>four spaces before<
>one space before<

So if you do mind to keep those spaces, please use the function at the beginning of my answer!

d) EXPLANATION of the sed syntax "find and replace" on multi-line strings used inside the function trim:

sed -n '
# If the first line, copy the pattern to the hold buffer
1h
# If not the first line, then append the pattern to the hold buffer
1!H
# If the last line then ...
$ {
    # Copy from the hold to the pattern buffer
    g
    # Do the search and replace
    s/^[ \t]*//g
    s/[ \t]*$//g
    # print
    p
}'

Solution 20 - String

This will remove all the whitespaces from your String,

 VAR2="${VAR2//[[:space:]]/}"

/ replaces the first occurrence and // all occurrences of whitespaces in the string. I.e. all white spaces get replaced by – nothing

Solution 21 - String

I've seen scripts just use variable assignment to do the job:

$ xyz=`echo -e 'foo \n bar'`
$ echo $xyz
foo bar

Whitespace is automatically coalesced and trimmed. One has to be careful of shell metacharacters (potential injection risk).

I would also recommend always double-quoting variable substitutions in shell conditionals:

if [ -n "$var" ]; then

since something like a -o or other content in the variable could amend your test arguments.

Solution 22 - String

var='   a b c   '
trimmed=$(echo $var)

Solution 23 - String

Assignments ignore leading and trailing whitespace and as such can be used to trim:

$ var=`echo '   hello'`; echo $var
hello

Solution 24 - String

Here's a trim() function that trims and normalizes whitespace

#!/bin/bash
function trim {
    echo $*
}

echo "'$(trim "  one   two    three  ")'"
# 'one two three'

And another variant that uses regular expressions.

#!/bin/bash
function trim {
    local trimmed="$@"
    if [[ "$trimmed" =~ " *([^ ].*[^ ]) *" ]]
    then 
        trimmed=${BASH_REMATCH[1]}
    fi
    echo "$trimmed"
}

echo "'$(trim "  one   two    three  ")'"
# 'one   two    three'

Solution 25 - String

To remove spaces and tabs from left to first word, enter:

echo "     This is a test" | sed "s/^[ \t]*//"

cyberciti.biz/tips/delete-leading-spaces-from-front-of-each-word.html

Solution 26 - String

This is the simplest method I've seen. It only uses Bash, it's only a few lines, the regexp is simple, and it matches all forms of whitespace:

if [[ "$test" =~ ^[[:space:]]*([^[:space:]].*[^[:space:]])[[:space:]]*$ ]]
then 
    test=${BASH_REMATCH[1]}
fi

Here is a sample script to test it with:

test=$(echo -e "\n \t Spaces and tabs and newlines be gone! \t  \n ")

echo "Let's see if this works:"
echo
echo "----------"
echo -e "Testing:${test} :Tested"  # Ugh!
echo "----------"
echo
echo "Ugh!  Let's fix that..."

if [[ "$test" =~ ^[[:space:]]*([^[:space:]].*[^[:space:]])[[:space:]]*$ ]]
then 
    test=${BASH_REMATCH[1]}
fi

echo
echo "----------"
echo -e "Testing:${test}:Tested"  # "Testing:Spaces and tabs and newlines be gone!"
echo "----------"
echo
echo "Ah, much better."

Solution 27 - String

Removing spaces to one space:

(text) | fmt -su

Solution 28 - String

This does not have the problem with unwanted globbing, also, interior white-space is unmodified (assuming that $IFS is set to the default, which is ' \t\n').

It reads up to the first newline (and doesn't include it) or the end of string, whichever comes first, and strips away any mix of leading and trailing space and \t characters. If you want to preserve multiple lines (and also strip leading and trailing newlines), use read -r -d '' var << eof instead; note, however, that if your input happens to contain \neof, it will be cut off just before. (Other forms of white space, namely \r, \f, and \v, are not stripped, even if you add them to $IFS.)

read -r var << eof
$var
eof

Solution 29 - String

I needed to trim whitespace from a script when the IFS variable was set to something else. Relying on Perl did the trick:

# trim() { echo $1; } # This doesn't seem to work, as it's affected by IFS

trim() { echo "$1" | perl -p -e 's/^\s+|\s+$//g'; }

strings="after --> , <-- before,  <-- both -->  "

OLD_IFS=$IFS
IFS=","
for str in ${strings}; do
  str=$(trim "${str}")
  echo "str= '${str}'"
done
IFS=$OLD_IFS

Solution 30 - String

trim() removes whitespaces (and tabs, non-printable characters; I am considering just whitespaces for simplicity). My version of a solution:

var="$(hg st -R "$path")" # I often like to enclose shell output in double quotes
var="$(echo "${var}" | sed "s/\(^ *\| *\$\)//g")" # This is my suggestion
if [ -n "$var" ]; then
 echo "[${var}]"
fi

The 'sed' command trims only leading and trailing whitespaces, but it can be piped to the first command as well resulting in:

var="$(hg st -R "$path" | sed "s/\(^ *\| *\$\)//g")"
if [ -n "$var" ]; then
 echo "[${var}]"
fi

Solution 31 - String

Python has a function strip() that works identically to PHP's trim(), so we can just do a little inline Python to make an easily understandable utility for this:

alias trim='python -c "import sys; sys.stdout.write(sys.stdin.read().strip())"'

This will trim leading and trailing whitespace (including newlines).

$ x=`echo -e "\n\t   \n" | trim`
$ if [ -z "$x" ]; then echo hi; fi
hi

Solution 32 - String

Use:

trim() {
    local orig="$1"
    local trmd=""
    while true;
    do
        trmd="${orig#[[:space:]]}"
        trmd="${trmd%[[:space:]]}"
        test "$trmd" = "$orig" && break
        orig="$trmd"
    done
    printf -- '%s\n' "$trmd"
}
  • It works on all kinds of whitespace, including newline,
  • It does not need to modify shopt.
  • It preserves inside whitespace, including newline.

Unit test (for manual review):

#!/bin/bash

. trim.sh

enum() {
    echo "   a b c"
    echo "a b c   "
    echo "  a b c "
    echo " a b c  "
    echo " a  b c  "
    echo " a  b  c  "
    echo " a      b  c  "
    echo "     a      b  c  "
    echo "     a  b  c  "
    echo " a  b  c      "
    echo " a  b  c      "
    echo " a N b  c  "
    echo "N a N b  c  "
    echo " Na  b  c  "
    echo " a  b  c N "
    echo " a  b  c  N"
}

xcheck() {
    local testln result
    while IFS='' read testln;
    do
        testln=$(tr N '\n' <<<"$testln")
        echo ": ~~~~~~~~~~~~~~~~~~~~~~~~~ :" >&2
        result="$(trim "$testln")"
        echo "testln='$testln'" >&2
        echo "result='$result'" >&2
    done
}

enum | xcheck

Solution 33 - String

I had to test the result (numeric) from a command but it seemed the variable with the result was containing spaces and some non printable characters. Therefore even after a "trim" the comparison was erroneous. I solved it by extracting the numerical part from the variable:

numerical_var=$(echo ${var_with_result_from_command} | grep -o "[0-9]*")

Solution 34 - String

This trims multiple spaces of the front and end

whatever=${whatever%% *}

whatever=${whatever#* }

Solution 35 - String

I created the following functions. I am not sure how portable printf is, but the beauty of this solution is you can specify exactly what is "white space" by adding more character codes.

    iswhitespace()
    {
        n=`printf "%d\n" "'$1'"`
        if (( $n != "13" )) && (( $n != "10" )) && (( $n != "32" )) && (( $n != "92" )) && (( $n != "110" )) && (( $n != "114" )); then
            return 0
        fi
        return 1
    }

    trim()
    {
        i=0
        str="$1"
        while (( i < ${#1} ))
        do
            char=${1:$i:1}
            iswhitespace "$char"
            if [ "$?" -eq "0" ]; then
                str="${str:$i}"
                i=${#1}
            fi
            (( i += 1 ))
        done
        i=${#str}
        while (( i > "0" ))
        do
            (( i -= 1 ))
            char=${str:$i:1}
            iswhitespace "$char"
            if [ "$?" -eq "0" ]; then
                (( i += 1 ))
                str="${str:0:$i}"
                i=0
            fi
        done
        echo "$str"
    }

#Call it like so
mystring=`trim "$mystring"`

Solution 36 - String

I found that I needed to add some code from a messy sdiff output in order to clean it up:

sdiff -s column1.txt column2.txt | grep -F '<' | cut -f1 -d"<" > c12diff.txt 
sed -n 1'p' c12diff.txt | sed 's/ *$//g' | tr -d '\n' | tr -d '\t'

This removes the trailing spaces and other invisible characters.

Solution 37 - String

Use this simple Bash parameter expansion:

$ x=" a z     e r ty "
$ echo "START[${x// /}]END"
START[azerty]END

Solution 38 - String

#!/bin/bash

function trim
{
    typeset trimVar
    eval trimVar="\${$1}"
    read trimVar << EOTtrim
    $trimVar
EOTtrim
    eval $1=\$trimVar
}

# Note that the parameter to the function is the NAME of the variable to trim, 
# not the variable contents.  However, the contents are trimmed.


# Example of use:
while read aLine
do
    trim aline
    echo "[${aline}]"
done < info.txt



# File info.txt contents:
# ------------------------------
# ok  hello there    $
#    another  line   here     $
#and yet another   $
#  only at the front$
#$



# Output:
#[ok  hello there]
#[another  line   here]
#[and yet another]
#[only at the front]
#[]

Solution 39 - String

var="  a b  "
echo "$(set -f; echo $var)"

>a b

Solution 40 - String

Use:

var=`expr "$var" : "^\ *\(.*[^ ]\)\ *$"`

It removes leading and trailing spaces and is the most basic solution, I believe. Not Bash built-in, but 'expr' is a part of coreutils, so at least no standalone utilities are needed like sed or AWK.

Solution 41 - String

Yet another solution with unit tests which trims $IFS from stdin, and works with any input separator (even $'\0'):

ltrim()
{
    # Left-trim $IFS from stdin as a single line
    # $1: Line separator (default NUL)
    local trimmed
    while IFS= read -r -d "${1-}" -u 9
    do
        if [ -n "${trimmed+defined}" ]
        then
            printf %s "$REPLY"
        else
            printf %s "${REPLY#"${REPLY%%[!$IFS]*}"}"
        fi
        printf "${1-\x00}"
        trimmed=true
    done 9<&0

    if [[ $REPLY ]]
    then
        # No delimiter at last line
        if [ -n "${trimmed+defined}" ]
        then
            printf %s "$REPLY"
        else
            printf %s "${REPLY#"${REPLY%%[!$IFS]*}"}"
        fi
    fi
}

rtrim()
{
    # Right-trim $IFS from stdin as a single line
    # $1: Line separator (default NUL)
    local previous last
    while IFS= read -r -d "${1-}" -u 9
    do
        if [ -n "${previous+defined}" ]
        then
            printf %s "$previous"
            printf "${1-\x00}"
        fi
        previous="$REPLY"
    done 9<&0

    if [[ $REPLY ]]
    then
        # No delimiter at last line
        last="$REPLY"
        printf %s "$previous"
        if [ -n "${previous+defined}" ]
        then
            printf "${1-\x00}"
        fi
    else
        last="$previous"
    fi

    right_whitespace="${last##*[!$IFS]}"
    printf %s "${last%$right_whitespace}"
}

trim()
{
    # Trim $IFS from individual lines
    # $1: Line separator (default NUL)
    ltrim ${1+"$@"} | rtrim ${1+"$@"}
}

Solution 42 - String

Array assignment expands its parameter splitting on the Internal Field Separator (space/tab/newline by default).

words=($var)
var="${words[@]}"

Solution 43 - String

The "trim" function removes all horizontal whitespace:

ltrim () {
    if [[ $# -eq 0 ]]; then cat; else printf -- '%s\n' "$@"; fi | perl -pe 's/^\h+//g'
    return $?
}

rtrim () {
    if [[ $# -eq 0 ]]; then cat; else printf -- '%s\n' "$@"; fi | perl -pe 's/\h+$//g'
    return $?
}

trim () {
    ltrim "$@" | rtrim
    return $?
}

Solution 44 - String

There are a few different options purely in BASH:

line=${line##+( )}           # strip leading whitespace;  no quote expansion!
line=${line%%+( )}           # strip trailing whitespace; no quote expansion!
line=${line// /}             # strip all whitespace
line=${line//[[:space:]]/}   # strip all whitespace
line=${line//[[:blank:]]/}   # strip all blank space

The former two require extglob be set/enabled a priori:

shopt -s extglob  # bash only

NOTE: variable expansion inside quotation marks breaks the top two examples!

The pattern matching behaviour of POSIX bracket expressions are detailed here. If you are using a more modern/hackable shell such as Fish, there are built-in functions for string trimming.

Solution 45 - String

The simplest and cheapest way to do this is to take advantage of echo ignoring spaces. So, just use

dest=$(echo $source)

for instance:

> VAR="   Hello    World   "
> echo "x${VAR}x"
x   Hello    World   x
> TRIMD=$(echo $VAR)
> echo "x${TRIMD}x"
xHello Worldx

Note that this also collapses multiple whitespaces into a single one.

Solution 46 - String

While it's not strictly Bash this will do what you want and more:

php -r '$x = trim("  hi there  "); echo $x;'

If you want to make it lowercase too, do:

php -r '$x = trim("  Hi There  "); $x = strtolower($x) ; echo $x;'

Solution 47 - String

#Execute this script with the string argument passed in double quotes !! 
#var2 gives the string without spaces.
#$1 is the string passed in double quotes
#!/bin/bash
var2=`echo $1 | sed 's/ \+//g'`
echo $var2

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questiontoo much phpView Question on Stackoverflow
Solution 1 - StringmakevoidView Answer on Stackoverflow
Solution 2 - StringMattyVView Answer on Stackoverflow
Solution 3 - StringbashfuView Answer on Stackoverflow
Solution 4 - Stringuser42092View Answer on Stackoverflow
Solution 5 - StringrkachachView Answer on Stackoverflow
Solution 6 - StringBrian CainView Answer on Stackoverflow
Solution 7 - StringGuruMView Answer on Stackoverflow
Solution 8 - StringVAmpView Answer on Stackoverflow
Solution 9 - StringPaul TomblinView Answer on Stackoverflow
Solution 10 - StringMooshuView Answer on Stackoverflow
Solution 11 - StringAdam RosenfieldView Answer on Stackoverflow
Solution 12 - StringflabdabletView Answer on Stackoverflow
Solution 13 - StringDaniel AlderView Answer on Stackoverflow
Solution 14 - StringMoses DavidowitzView Answer on Stackoverflow
Solution 15 - StringgMaleView Answer on Stackoverflow
Solution 16 - StringNOYBView Answer on Stackoverflow
Solution 17 - Stringghostdog74View Answer on Stackoverflow
Solution 18 - StringpojoView Answer on Stackoverflow
Solution 19 - StringLuca BorrioneView Answer on Stackoverflow
Solution 20 - StringAlpesh GediyaView Answer on Stackoverflow
Solution 21 - StringMykennaCView Answer on Stackoverflow
Solution 22 - StringultrView Answer on Stackoverflow
Solution 23 - StringevanxView Answer on Stackoverflow
Solution 24 - StringNicholas SushkinView Answer on Stackoverflow
Solution 25 - StringZomboView Answer on Stackoverflow
Solution 26 - Stringuser712624View Answer on Stackoverflow
Solution 27 - StringgardziolView Answer on Stackoverflow
Solution 28 - StringGregorView Answer on Stackoverflow
Solution 29 - StringTrinitronXView Answer on Stackoverflow
Solution 30 - StringAvengerView Answer on Stackoverflow
Solution 31 - StringjohncsView Answer on Stackoverflow
Solution 32 - StringAlois MahdalView Answer on Stackoverflow
Solution 33 - StringOlivier MeuriceView Answer on Stackoverflow
Solution 34 - Stringgretelmk2View Answer on Stackoverflow
Solution 35 - StringcmeubView Answer on Stackoverflow
Solution 36 - Stringuser1186515View Answer on Stackoverflow
Solution 37 - StringGilles QuenotView Answer on Stackoverflow
Solution 38 - StringRazor5900View Answer on Stackoverflow
Solution 39 - StringdavideView Answer on Stackoverflow
Solution 40 - StringmoskitView Answer on Stackoverflow
Solution 41 - Stringl0b0View Answer on Stackoverflow
Solution 42 - StringDavid FarrellView Answer on Stackoverflow
Solution 43 - StringMario PalumboView Answer on Stackoverflow
Solution 44 - StringAdam EricksonView Answer on Stackoverflow
Solution 45 - StringEric YriarteView Answer on Stackoverflow
Solution 46 - StringDavid NewcombView Answer on Stackoverflow
Solution 47 - Stringa.saurabhView Answer on Stackoverflow