0

Is there any way to expand variables inside commands? It's hard for me to explain what I want to achieve, so I'll demonstrate it:

Let's say I have this construct:

var1="\${var2} -eq 7"

if [ ${var1} ]; do....

And the desired output is:

if [ ${var2} -eq 7 ]; do....

Now obviously that doesn't work, but how would I make something like this work?

  • 4
    That's an [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). What are you actually trying to achieve? (Why are you storing script fragments in variables?) – melpomene May 11 '19 at 21:06
  • You could use `eval`, but that is generally considered a bad idea because of security concerns. You probably need to reconsider your design. For example, by using functions instead, although without knowing *why* you want to do this it is difficult to advise. – cdarke May 11 '19 at 21:31
  • This is just a curiosity of mine, if it is possible to expand a variable inside a command, and for that variable to actually play out as parts of the command. For example, another "use case" would be `var1="status httpd"` and then `systemctl ${var1}`. So basically there's nothing I actually want to achieve, I just want to know if it's possible, and if it is, how would it be done. Thanks – Lhakryma DL May 11 '19 at 21:41
  • See [BashFAQ #50](http://mywiki.wooledge.org/BashFAQ/050) for a discussion of relevant best practices, and [BashFAQ #48](https://mywiki.wooledge.org/BashFAQ/048) for a discussion of `eval`. – Charles Duffy May 11 '19 at 22:26
  • `systemctl $var1` will work exactly as you expect, as long as you don't quote the expansion. The problem with the example in the original question is that the expansion itself needs to be expanded because it contains the name of a variable. That only works in numerical contexts (in bash). – rici May 12 '19 at 01:12

3 Answers3

0

You should use functions for this sort of thing. You can also use eval, but please don't.

$ equalsSeven() (($1 == 7))
$ if equalsSeven 7; then echo Presto; fi
Presto

man bash, /Compound

vintnes
  • 2,014
  • 7
  • 16
0

For that, is evil eval:

var1="\${var2} -eq 7"
var2=7
if eval [ ${var1} ]; then
    echo var2 is 7
fi

Note that if ...; do is invalid, after the if expression comes then, not do.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • Yes, sorry I wasn't paying attention, thanks, now I'll read up on why eval is a bad practice – Lhakryma DL May 11 '19 at 22:05
  • 1
    `eval "[ $var1 ]"` with the quotes is better form (not that using eval is good form at all). Otherwise you get an extra round of string-splitting and glob expansion before your evaluation even starts! – Charles Duffy May 11 '19 at 22:27
0

Since bash's numerical evaluation does actually expand variables (and, as a bonus, doesn't require them to be signaled with a $) you can achieve this in bash quite easily:

$ comparison='x==7'
$ x=7
$ if ((comparison)); then echo yup; else echo nope; fi
yup
$ x=8
$ if ((comparison)); then echo yup; else echo nope; fi
nope

This works because ((…)) and $((…)) are numerical contexts. So is the index of an array, and assignment to a variable declared as numeric. (However, this feature is almost as evil as eval. Avoid numeric evaluation of unchecked input.)

rici
  • 234,347
  • 28
  • 237
  • 341