Can't understand the Bash behaviour

Hello!

Can’t understand the Bash behaviour on such case:

> echo $(seq -s" " 1 +2 15)

It returns string (because -s" " is defined) of numbers: 1 3 5 7 9 11 13 15

Now there is a simple script:


#!/bin/bash

for n in $(seq -s" " 1 +2 15)
do
echo $n
done

exit 0

It returns column of the same numbers, although -s" " is also defined.

Can someone explain this Bash behaviour, please? :crazy:

Instead of only telling the story that should go with the facts, why not posting the facts also:

henk@boven:~> echo $(seq -s" " 1 +2 15)
1 3 5 7 9 11 13 15
henk@boven:~> for n in $(seq -s" " 1 +2 15)
> do
> echo $n
> done
1
3
5
7
9
11
13
15
henk@boven:~>

And I do not understand your worrying. When I do directly

henk@boven:~> for n in 1 3 5 7 9 11 13 15
> do
> echo $n
> done
1
3
5
7
9
11
13
15
henk@boven:~>

that is the same. The seq tool gives you a list of numbers separated by blank spaces. And that is what is interpreted by the for construct.

Maybe you should explain what you want to achive and not a step you took (and that might be on the wrong path to achievement).

The ‘for’ line is looping over everything returned from the ‘seq’ command,
and then it is sending each argument to the ‘echo’ command, which is
printing it; by default, echo prints something and ends it with a newline.

It may help if you explained what you thought SHOULD happen. Want them
all on one line? Try using ‘echo -n’ instead of ‘echo’.


Good luck.

If you find this post helpful and are logged into the web interface,
show your appreciation and click on the star below…

I’m trying to understand the logic (yes, I’m the beginner and ask beginner’s questions) how Bash works. For example:

> seq 1 +2 15

will return the** column** of numbers and

> echo $(seq 1 +2 15)

will return the** string** of numbers. Why so?

In script I wanna to achive ** string **output after ‘for… do… done’ construction is worked off.

Thanks for your help!

Again, please do not tell stories like doing X will return column, Bur do it on your terminal and copy/paste it here as I did. And copy/paste between CODE tags, it is the # button in the tool bar of the post editor.

Remind that the words “string” and “column” might have different meanings in this area.

In any case, you have a for loop and the echo inside. That means that there will be as many executions of the echo command as there are executions of the loop. And those echo command each output a line with a number. it is like you would have typed:

echo 1
echo 3
echo 5
echo 7
echo 9
echo 11
echo 13
echo 15

Here you are:


k_mikhail@linux-mk500:~> seq -s" " 1 +2 15
1 3 5 7 9 11 13 15
k_mikhail@linux-mk500:~> seq 1 +2 15
1
3
5
7
9
11
13
15
k_mikhail@linux-mk500:~> echo $(seq -s" " 1 +2 15)
1 3 5 7 9 11 13 15
k_mikhail@linux-mk500:~> echo $(seq 1 +2 15)
1 3 5 7 9 11 13 15
k_mikhail@linux-mk500:~>

'echo 'takes a list of arguments to be printed. It does not print exactly
what it is given unless what it is given is quoted. You’re not quoting
the ‘seq’ output so it does not matter if you have one space, ten spaces,
newlines, or tabs in there; echo will just send each thing it sees that is
NOT whitespace (in your case, strings of digits) out in one big line.

‘for’ works similarly; it cares about getting arguments which are
delimited by whitespace; again, newline, one space, ten spaces… it
doesn’t matter. As a result, for operates on each string (of digits) as a
single argument, and then sends it to echo. In the for-loop case, echo is
called individually for each thing ‘for’ sends to it, and echo by default
puts a newline after things it prints, so you get a “column” as you
described it.


Good luck.

If you find this post helpful and are logged into the web interface,
show your appreciation and click on the star below…

Hi,

Don’t loop over the command substitution because it will break if unquoted, use an array or if you really insists quote the command substitution $( ) (which is the correct way of doing it), Because of word splitting. Someone already mention that in here, or use printf as a work around.
Quoting is often neglected in shell grammar but it is the most important part it is not just a decoration.

echo "$(seq -s" " 1 +2 15)"

or

printf  '%d
' $(seq -s" " 1 +2 15)

That said seq is an external utility to the shell and you don’t need it if you just want to do some counting over a loop. The cfor style for loop works with bash.

for ((i=1;i<=15;i+=2)); do echo "$i"; done

Even a while loop can do that.

i=1; while ((i<=15)); do echo $i; ((i+=2)); done

:wink:

Hi,

I am not a seq user but bash has nothing to do with that behaviour. Reading the seq man page it states the use of the **-s **flag which means.

-s, --separator=STRING   use STRING to separate numbers (default: 
)

So you told seq to use a space -s " " as a separator and you expect bash to do something else :wink: .
Since by default numbers are separated by a newline you can just do.

echo "$(seq 1 +2 15)"

without the loop.

Thanks to everybody - will try the variations!

Hi,

If you really want to print in one line use printf instead of echo.
Also you can put the start and end plus the counter in a variable.


start=1
end=15
counter=2

for ((i=start;i<=end;i+=counter)); do printf '%d ' "$i"; done

or


start=1
end=15
counter=2

i=$start; while ((i<=end)); do printf '%d ' "$i"; ((i+=counter)); done

good luck.

All nice solutions, but what was the question? :expressionless:

Right, sorry for the noise maybe i just got carried away :slight_smile:

I do not think you need to appologize, all here try to help, inclusing you. But several times the OP was asked what he realy wanted to achieve. So people could help him in a direction that may lead to sucess. No real answer thus far.

IMHO he only told us what he saw happening. And that was all correct and per definition as it should happen. But his question (well, is it a question or is it a conclusion?) was: Can’t understand the Bash behaviour.

That is of course quite possible, because it is not all that easy when one starts using bash (or most other shells). Some tried to explain why he sees things happenning as he (and we) see them happening.

It seems that he prefers to find a solution to what he wants by struggling on with the added knowledge provided above. That is imho perfect OK. Findiing things yourself is often rewarding and not easily forgotten.

But I assume, some people (me included) are curious about what he wants :stuck_out_tongue: