What is the difference between these two things?
Asked Answered
B

2

6

I just wanted to know what is the difference between:

echo {$number1..$number2}

AND

eval echo {$number1..$number2}

Of course, imagine that there is a value in $number1 and $number2. With the first option is just not working, but with the second option it works. I'm not the typical guy that only want something to work, I want to understand why it happens like that so, why exactly is this happening like this?

Benedictus answered 3/2, 2019 at 0:7 Comment(4)
An eval could execute any command.Timofei
yes but, in the first form I'm executing the command too. So what is the real difference? the process?Lorca
This answer on a related question explains why brace expansion doesn't work together with parameter expansionBeaulieu
The bash manpage isn't the easiest read but the EXPANSION section may be of some help.Parhe
B
9

Why the first expression does not work as expected

  1. Brace expansion is executed before variable expansion. $number1..$number2 is not a valid sequence expression, so the whole expression is left unchanged.
  2. After that, variable expansion takes place, resulting in the expression {1..3} (given that number1=1 and number2=3).

Why the second expression does

Your second example works the same, except that the result of variable expansion ({1..3}) is passed to Bash again via eval, giving brace expansion a second chance: 1..3 is a correctly formed sequence expression and therefore brace expansion yields the expected result:

1 2 3

Avoid using eval

Using eval should generally be avoided, as it easily introduces security problems: If number1 or number2 receive input and are not properly sanitized, malicious code can be injected into your program. See this related question for ways to replace eval in various use cases.

In your specific example, the sequence could instead be created by a for loop combined with arithmetic evaluation:

for ((i=number1 ; i<=number2; i+=1)); do echo -n "$i" ; done | xargs
1 2 3

A popular non-Bash solution would be to use seq (as pointed out by Walter A in his answer) as in seq "$number1" "$number2" | xargs.

Note: xargs joins multi-line output to a single line in these examples.

Further information

This answer to a related question gives more information on the topic.

Also, the EXPANSION section in the bash(1) manual page is pretty informative on sequence and workings of different expansion mechanisms.

Boatel answered 3/2, 2019 at 1:20 Comment(0)
H
0

The substitution of the variables is to late.
You can avoid eval with

seq -s " " "$number1" "$number2"
Hessney answered 3/2, 2019 at 10:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.