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?

user3856370
  • 237
  • 2
  • 8

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.

Kamil Maciorowski
  • 19,242
  • 1
  • 50
  • 94
  • 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"
roaima
  • 107,089
  • 14
  • 139
  • 261
  • 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`?](https://unix.stackexchange.com/questions/65803/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 – roaima Jan 11 '21 at 17:24