Sign up ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.
echo ' 1 2     3  '|sed 's/[[:space:]]*/_/g'

I want to see _1_2_____3__ as the output. Instead, I am seeing _1_2_3_ as the output. What am I doing wrong??

The other thing confusing me, which I forgot to put in the above example, is why this:

echo ' test1 test2  ' | sed 's/[[:space:]]*/_/g'

shows this:


How can [[:space:]] match between t and e and s...?

share|improve this question
The posted answer already answer that too. * matches 0 or more spaces. – Leiaz Aug 16 '14 at 19:03
@Leiaz Hmmm....didn't think of that. So how do I match one or more? – BenjiWiebe Aug 16 '14 at 19:03
With + echo ' test1 test2 ' | sed 's/[[:space:]]\+/_/g' – Leiaz Aug 16 '14 at 19:05
@Leiaz: Use 's/[[:space:]]\{1,\}/_/g' for portability. – cuonglm Aug 16 '14 at 19:08
@Leiaz Oh yes...been too long since I've studied regex. I do remember now about '+'. – BenjiWiebe Aug 16 '14 at 19:14

3 Answers 3

up vote 7 down vote accepted

Because you use *, meaning it matches 0 or more spaces. So zero or multiple spaces is substitued by one underscore _.


$ echo ' 1 2     3  ' | sed 's/[[:space:]]/_/g'

Remember that [[:space:]] also matches tab, newline, carriage return.


share|improve this answer

You've already got an answer but I want to point out that in such simple scenario there is no need to be fancy:

$ echo ' 1 2     3  ' | sed 's/ /_/g'

If you want to replace only spaces and tabs you can use [ \t] construct as well:

$ echo -e " 1\t2     3  " | sed 's/[ \t]/_/g'
share|improve this answer

The question asks explicitly about sed, and it's a very valid question about sed regexp syntax.

But in case the underlying question is about replacing spaces by _ really, here is an alternative answer using the "right tool for the job" for translating characters, which is tr. (man tr).

The command tr abc 123 replaces the chars of the first list with the corresponding chars in the second. Thus, tr ' ' _ replaces space by underscore.

$ echo ' 1 2     3  ' | tr ' ' _

To show the more general case, including various kinds of whitespace like your example,
here is the output for only translating the normal space character ' ' for comparison:

echo ' 1 2     3  x\ny\tz' | tr ' ' _        
y       z

And here is the output when translating all characters of the class :space: to _:

echo ' 1 2     3  x\ny\tz' | tr '[:space:]' _

(Note there is no newline at the end of the output - and there is a _ after the z.)
This can be written explicitly as tr ' \t\n' _, which is the short form of tr ' \t\n' ___.

$ echo ' 1 2     3  x\ny\tz' | tr ' \t\n' _    
share|improve this answer
I know about tr. I will forever regret the example I initially posted. I was specifically wondering how to replace a sequence of whitespace with one character, even though I did a poor job of explaining that. – BenjiWiebe Aug 19 '14 at 1:35
I really did not post my real problem at first, just a portion of it. I thought I could figure out the main problem if I could get over the puzzling behavior of my first example. – BenjiWiebe Aug 19 '14 at 1:36
Oh, you were clear enough that you ask about sed; But even if the answer is not helpful for you, it may help someone else reading the questions and answers. Someone who uses sed like in the answers should at least know that there is a much tool simpler tool for this. – Volker Siegel Aug 19 '14 at 13:50

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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