109

I have the following code:

for x in "${array[@]}"
do
  echo "$x"
done

The results are something like this (I sort these later in some cases):

1
2
3
4
5

Is there a way to print it as 1 2 3 4 5 instead? Without adding a newline every time?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ricky162
  • 1,231
  • 3
  • 10
  • 10
  • That would be slightly trickier to sort. – melpomene Jun 24 '16 at 20:12
  • aside: http://shellcheck.net/ is your friend. – Charles Duffy Jun 24 '16 at 20:21
  • ...also, "tried `printf`" doesn't show *how* you tried using `printf`. Details matter. :) – Charles Duffy Jun 24 '16 at 20:23
  • `array=( 1 2 3 4 5 ); printf '%s ' "${array[@]}"; echo` -- prints a single line with `1 2 3 4 5 ` in its contents. – Charles Duffy Jun 24 '16 at 20:27
  • ...re: your edit, also include how you're populating the array. I'm guessing you're using `readarray` or `mapfile` without `-t`, which is putting literal newlines in your data. – Charles Duffy Jun 24 '16 at 20:28
  • ...and really, if you're using `readarray` or `mapfile`, why not sort your data on the input side instead of the output side? `readarray -t array < <(sort input.txt)` – Charles Duffy Jun 24 '16 at 20:29
  • @CharlesDuffy yeah I think I am populating with new lines. Thanks. I'll have to find another approach. – ricky162 Jun 24 '16 at 20:33
  • ...you could also add `declare -p array` and its output to your question, which will give you a line that reproduces the data at hand. Assuming that that data is what you actually *want*, we could then give you a fix that works with it, such as `printf '%s ' "${array[@]%$'\n'}"` (if my guess re: trailing newlines is correct). – Charles Duffy Jun 24 '16 at 20:33
  • actually, just preprocessing with `array=( "${array[@]%$'\n'}" )` will do, if it's only trailing, UNIX-style newlines that are an issue. – Charles Duffy Jun 24 '16 at 20:34
  • 1
    ...btw, this is part of why we ask for questions to contain a minimal, **complete, verifiable** example -- to make this complete and verifiable it would have needed to include actual values for the array that reproduced the issue as part of the question, which would have meant we wouldn't have been fumbling around before figuring out your actual problem; see also http://stackoverflow.com/help/mcve. – Charles Duffy Jun 24 '16 at 20:37
  • @CharlesDuffy I thought that's what I was doing... – ricky162 Jun 24 '16 at 20:41
  • if you'd had `array=( 1 2 3 4 5 )` or an equivalent which actually produced your bug, then you would have been. That's part of why *testing* your example in a clean environment (http://ideone.com/ is ideal, since that way you *know* you aren't relying on something just on your machine) before hitting "post" is good practice. – Charles Duffy Jun 24 '16 at 20:45
  • 1
    The canonical is *["echo -n" prints "-n"](https://stackoverflow.com/questions/11193466/)*. – Peter Mortensen Nov 05 '21 at 14:43

5 Answers5

197

Yes. Use the -n option:

echo -n "$x"

From help echo:

-n do not append a newline

This would strips off the last newline too, so if you want you can add a final newline after the loop:

for ...; do ...; done; echo

Note:

This is not portable among various implementations of echo builtin/external executable. The portable way would be to use printf instead:

printf '%s' "$x"
oguz ismail
  • 1
  • 16
  • 47
  • 69
heemayl
  • 39,294
  • 7
  • 70
  • 76
  • 4
    thanks it just prints out the '-n' instead before each number – ricky162 Jun 24 '16 at 20:12
  • 2
    Any reason to put the `echo` approach before the portable one? – Charles Duffy Jun 24 '16 at 20:22
  • @CharlesDuffy As OP was using `echo` already, so thought about going with that first.. – heemayl Jun 24 '16 at 20:23
  • @CharlesDuffy thanks I tried the edit. Still the same thing... – ricky162 Jun 24 '16 at 20:24
  • @ricky162, again, **details matter**. Have to see *how* you tried it to know how it failed. Now, `printf '%s' "$x"` has its own problems, inasmuch as it doesn't put any spaces between the items (so it would emit `12345`, not `1 2 3 4 5`), but it certainly doesn't print any newlines unless the array itself contains newline literals. – Charles Duffy Jun 24 '16 at 20:24
  • 2
    @ricky162, ...if you're seeing behavior other than that, then you necessarily have other problems -- such as data that doesn't represent what you put in the question; content with newline literals embedded in the array body, for instance. – Charles Duffy Jun 24 '16 at 20:26
  • 1
    @ricky162 did you run the script with sh instead of bash? with bash it works as expected, with sh it prints literal -n – lilalinux Apr 22 '22 at 12:40
10
printf '%s\n' "${array[@]}" | sort | tr '\n' ' '

printf '%s\n' -- more robust than echo and you want the newlines here for sort's sake "${array[@]}" -- quotes unnecessary for your particular array, but good practice as you don't generally want word-spliting and glob expansions there

oguz ismail
  • 1
  • 16
  • 47
  • 69
Petr Skocik
  • 58,047
  • 6
  • 95
  • 142
5

You don't need a for loop to sort numbers from an array.

Use process substitution like this:

sort <(printf "%s\n" "${array[@]}")

To remove new lines, use:

sort <(printf "%s\n" "${array[@]}") | tr '\n' ' '
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
anubhava
  • 761,203
  • 64
  • 569
  • 643
3

If, for whatever reason, -n doesn't fix this for you, you can also add \c to the end of the thing to be echo'd:

echo "$x\c"
Edward Loveall
  • 1,983
  • 1
  • 19
  • 34
  • This is just as poorly portable as `echo -n`, and less widely supported. – tripleee Jun 27 '22 at 11:41
  • Thanks, but I tried the `-n` in some cases and it did not work. This was the only way I could make it work. – Edward Loveall Jun 28 '22 at 12:02
  • 1
    @tripleee actually, echo -n is NOT portable at all: https://unix.stackexchange.com/tags/echo/info - in short: echo -n will actually print -n on some systems, specifically on MacOS "sh". this answer is a valid option. – lzap Jun 28 '22 at 12:12
  • @lzap That's precisely what I was saying. Both of these should be avoided in favor of the properly portable - as well as vastly more versatile - `printf`. – tripleee Jun 28 '22 at 13:00
2

You can also do it this way:

array=(1 2 3 4 5)
echo "${array[@]}"
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ezzeddin
  • 499
  • 2
  • 5
  • 25