How to replace multiple spaces with a single space using Bash? [duplicate]
Using tr
:
$ echo "too many spaces." | tr -s ' 'too many spaces
man tr
:
-s, --squeeze-repeats replace each sequence of a repeated character that is listed in the last specified SET, with a single occurrence of that characā ter
Edit: Oh, by the way:
$ s="foo bar"$ echo $sfoo bar$ echo "$s"foo bar
Edit 2: On the performance:
$ shopt -s extglob$ s=$(for i in {1..100} ; do echo -n "word " ; done) # 100 times: word word word...$ time echo "${s//+([[:blank:]])/ }" > /dev/nullreal 0m7.296suser 0m7.292ssys 0m0.000s$ time echo "$s" | tr -s ' ' >/dev/nullreal 0m0.002suser 0m0.000ssys 0m0.000s
Over 7 seconds?! How is that even possible. Well, this mini laptop is from 2014 but still. Then again:
$ time echo "${s//+( )/ }" > /dev/nullreal 0m1.198suser 0m1.192ssys 0m0.000s
Here is a way to do this using pure bash
and extglob
:
s="too many spaces."shopt -s extglobecho "${s//+([[:blank:]])/ }"
too many spaces.
- Bracket expression
[[:blank:]]
matches a space or tab character +([[:blank:]])
matches one or more of the bracket expression (requiresextglob
)
Another simple sed
expression using BRE is:
sed 's/[ ][ ]*/ /g'
For example:
$ echo "too many spaces." | sed 's/[ ][ ]*/ /g'too many spaces.
There are a number of ways to skin the cat.
If the enclosed whitespace could consist of mixed spaces
and tabs
, then you could use:
sed 's/\s\s*/ /g'
And if you simply want to have bash word-splitting handle it, just echo your string without quotes, e.g.
$ echo "too many spaces." | while read line; do echo $line; donetoo many spaces.
Continuing with that same thought, if your string with spaces is already stored in a variable, you can simply use echo
unquoted within command substitution to have bash remove the additional whitespace for your, e.g.
$ foo="too many spaces."; bar=$(echo $foo); echo "$bar"too many spaces.