3

I have the following brace expansion (bash shell):

echo -e {0..4..2}" "{0..2..2}"\n"

I expected this to produce

0 0
0 2
2 0
2 2
4 0
4 2

but every line of the output except the first has a leading space and there is an extra blank line at the end that I didn't expect. Why is this. Is there a simple way to fix it? Obviously I can do something clunky like pipe to sed 's/^ //', but is there a prettier way without piping to extra commands?

2 Answers2

18

echo prints its arguments separated by spaces, even if they include (or generate) newline characters. Additionally it adds one newline character at the end of its output (unless it's echo -n).

Use printf:

printf '%s\n' {0..4..2}" "{0..2..2}

When echo does something unexpected, always consider printf. After you get familiar with printf it may even become your first choice.

  • 3
    Even when echo doesn't do something unexpected, consider using printf instead. echo can't be unpredictable if it isn't used at all :) – chepner Jan 11 '21 at 15:54
2

The reason you're getting a space that the beginning of each line complicated. The echo command spits out its arguments separated by space. Each argument consists of an expansion from {0..4..2} and {0..2..2} followed by a newline. When you put those two together you see that the space at the beginning of each line is actually the space that echo emits between items.

There are a couple of solutions that spring to mind. The first is that if you don't mind having a blank line at the beginning of the output you could put the newline at the start of each expansion,

echo -e "\n"{0..4..2}" "{0..2..2}

Another is to loop across the arguments and print them separately

for seq in {0..4..2}" "{0..2..2}; do echo "$seq"; done

or

echo -e {0..4..2}"\n"{0..2..2} | xargs printf "%d %d\n"
Chris Davies
  • 116,213
  • 16
  • 160
  • 287
  • Note that echo -e is quite wildly unreliable. The POSIX standard doesn't allow it to do anything but print -e on output, and depending on which runtime flags are active (flags which can be set through environment variables, or at compile time, or through explicit code), bash sometimes will comply with that standard and make echo -e foo print -e foo. Stephane's excellent answer to Why is printf better than echo? is on-point. – Charles Duffy Jan 11 '21 at 16:39
  • Yes... I'd have switched it to printf but by the time I was ready to hit [Save] I realised that option had already been taken by a different answer. In the end I decided that part of my answer should have minimal changes from the question – Chris Davies Jan 11 '21 at 17:24