41

How to remove extra spaces in variable HEAD?

HEAD="    how to  remove    extra        spaces                     "

Result:

how to remove extra spaces
F1Linux
  • 3,580
  • 3
  • 25
  • 24
Charlie
  • 2,061
  • 4
  • 21
  • 21
  • 1
    Do you really want to remove the whitespace in `HEAD`, or just provide the expansion of `$HEAD` without whitespace to another command? The shell provides better tools for controlling the output of expansion than it does tools for just mutating a variable in place. – kojiro May 06 '15 at 03:11
  • As you can see [here](https://unix.stackexchange.com/a/145981/337382): tr -s " " < file – Mark Feb 27 '19 at 03:27

10 Answers10

47

Try this:

echo "$HEAD" | tr -s " "

or maybe you want to save it in a variable:

NEWHEAD=$(echo "$HEAD" | tr -s " ")

Update

To remove leading and trailing whitespaces, do this:

NEWHEAD=$(echo "$HEAD" | tr -s " ")
NEWHEAD=${NEWHEAD%% }
NEWHEAD=${NEWHEAD## }
gniourf_gniourf
  • 44,650
  • 9
  • 93
  • 104
jman
  • 11,334
  • 5
  • 39
  • 61
34

Using awk:

$ echo "$HEAD" | awk '$1=$1'
how to remove extra spaces
Guru
  • 16,456
  • 2
  • 33
  • 46
14

Take advantage of the word-splitting effects of not quoting your variable

$ HEAD="    how to  remove    extra        spaces                     "
$ set -- $HEAD
$ HEAD=$*
$ echo ">>>$HEAD<<<"
>>>how to remove extra spaces<<<

If you don't want to use the positional paramaters, use an array

ary=($HEAD)
HEAD=${ary[@]}
echo "$HEAD"

One dangerous side-effect of not quoting is that filename expansion will be in play. So turn it off first, and re-enable it after:

$ set -f
$ set -- $HEAD
$ set +f
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • This ought to be the accepted answer. This, or [the answer from kojiro](http://stackoverflow.com/a/30066976/1877426). – lagweezle Dec 30 '15 at 18:25
  • 1
    Note that the behavior depends on the value `IFS`. With the default `IFS`, namely `$' \t\n'` you'll also replace tabs and newlines by a space. – gniourf_gniourf Jun 13 '16 at 18:20
11

This horse isn't quite dead yet: Let's keep beating it!*

Read into array

Other people have mentioned read, but since using unquoted expansion may cause undesirable expansions all answers using it can be regarded as more or less the same. You could do

set -f
read HEAD <<< $HEAD
set +f

or you could do

read -rd '' -a HEAD <<< "$HEAD"  # Assuming the default IFS
HEAD="${HEAD[*]}"

Extended Globbing with Parameter Expansion

$ shopt -s extglob
$ HEAD="${HEAD//+( )/ }" HEAD="${HEAD# }" HEAD="${HEAD% }"
$ printf '"%s"\n' "$HEAD"
"how to remove extra spaces"

*No horses were actually harmed – this was merely a metaphor for getting six+ diverse answers to a simple question.

kojiro
  • 74,557
  • 19
  • 143
  • 201
  • 1
    This is the only answer that really makes sense here. It's sad ugly hacks and semi-broken answers are upvoted instead… – Michał Górny Dec 19 '15 at 18:41
  • 2
    In honor of this answer (which avoids echo, shell expansion and all the other pitfalls all the other answers went into), I deleted my own incorrect answer. – mogsie Dec 21 '15 at 01:17
  • Two more notes: `read` needs `-r` to prevent processing backslash escapes, and `-d ""` to normalize newlines rather than truncating at first newline. Both options need to be passed before `-a`. – Michał Górny Jul 02 '20 at 07:13
  • You introduced an error when applying @MichałGórny's suggestion: `read -rd'' -a HEAD` **will not work**, it needs to be `read -r -d '' -a HEAD` or `read -rd '' -a HEAD`. Also, IFS should be mentioned, as this will only work if `IFS` contains the space character. – Fonic May 03 '21 at 07:48
6

Here's how I would do it with sed:

string='    how to  remove    extra        spaces                     '
echo "$string" | sed -e 's/  */ /g' -e 's/^ *\(.*\) *$/\1/'

=> how to remove extra spaces   # (no spaces at beginning or end)

The first sed expression replaces any groups of more than 1 space with a single space, and the second expression removes any trailing or leading spaces.

gniourf_gniourf
  • 44,650
  • 9
  • 93
  • 104
ndbroadbent
  • 13,513
  • 3
  • 56
  • 85
3

echo -e " abc \t def "|column -t|tr -s " "

column -t will:

  1. remove the spaces at the beginning and at the end of the line
  2. convert tabs to spaces

tr -s " " will squeeze multiple spaces to single space


BTW, to see the whole output you can use cat - -A: shows you all spacial characters including tabs and EOL:

echo -e " abc \t def "|cat - -A

output: abc ^I def $

echo -e " abc \t def "|column -t|tr -s " "|cat - -A

output: abc def$

lisrael1
  • 348
  • 2
  • 7
2

Whitespace can take the form of both spaces and tabs. Although they are non-printing characters and unseen to us, sed and other tools see them as different forms of whitespace and only operate on what you ask for. ie, if you tell sed to delete x number of spaces, it will do this, but the expression will not match tabs. The inverse is true- supply a tab to sed and it will not match spaces, even if the number of them is equal to those in a tab.

A more extensible solution that will work for removing either/both additional space in the form of spaces and tabs (I've tested mixing both in your specimen variable) is:

echo $HEAD | sed 's/^[[:blank:]]*//g'

or we can tighten-up @Frontear 's excellent suggestion of using xargs without the tr:

echo $HEAD | xargs

However, note that xargs would also remove newlines. So if you were to cat a file and pipe it to xargs, all the extra space- including newlines- are removed and everything put on the same line ;-).

Both of the foregoing achieved your desired result in my testing.

F1Linux
  • 3,580
  • 3
  • 25
  • 24
1

Try this one:

echo '    how to  remove    extra        spaces                     ' | sed 's/^ *//g' | sed 's/$ *//g' | sed 's/   */ /g'

or

HEAD="    how to  remove    extra        spaces                     "
HEAD=$(echo "$HEAD" | sed 's/^ *//g' | sed 's/$ *//g' | sed 's/   */ /g')
gniourf_gniourf
  • 44,650
  • 9
  • 93
  • 104
Shoo Limberger
  • 277
  • 2
  • 11
1

echo variable without quotes does what you want:

HEAD="    how to  remove    extra        spaces      "
echo $HEAD

# or assign to new variable
NEW_HEAD=$(echo $HEAD)
echo $NEW_HEAD

output: how to remove extra spaces

Oleksandr Shmyrko
  • 1,720
  • 17
  • 22
1

I would make use of tr to remove the extra spaces, and xargs to trim the back and front.

TEXT="     This          is  some                             text   "
echo $(echo $TEXT | tr -s " " | xargs)

# [...]$ This is some text
Frontear
  • 1,150
  • 12
  • 25