Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I am having some problem with bash. I want to export an environment variable whose value contains a variable but I don't want that variable (which is within the value) to be evaluated during the export process. i.e.

export STY=for i in {0..3}; do echo $i; done

so my requirement is that when I echo STY, the output that I need should be

echo $STY
for i in {0..3}; do echo $i; done 

But $i is evaluated during export. I need to preserve it as it is.

Thanks alot for your help.

share|improve this question
    
Are you saying that echo $STY should print out the actual text for i in {0..3}; do echo $i; done? Or are you saying that echo $STY should execute that for-loop? (I ask because, although it sounds to me like the former, Borealid below seems to think you really want the latter.) –  ruakh Feb 25 '12 at 1:45
    
Actually I want to setup the environment variable that will contain some code but will be executed in some other bash script. –  Shahzad Feb 25 '12 at 2:01
    
How are you executing the command in the variable? Command substitution? –  Daniel Feb 25 '12 at 2:57
    
I am simply specifying the name of the variable like $hello –  Shahzad Feb 25 '12 at 2:58
1  
Change double quote to single quote, then try: eval $hello –  kev Feb 25 '12 at 3:10
add comment

migrated from stackoverflow.com Feb 26 '12 at 5:41

This question came from our site for professional and enthusiast programmers.

4 Answers

If you want what you said you wanted:

export STY="for i in {0..3}; do echo \$i; done"

If you want what you probably actually meant:

function STY() {
    for i in {0..3}; do echo $i; done
}
export -f STY
share|improve this answer
1  
He could just use single quotes, i.e. export STY='for i in {0..3}; do echo $i; done' –  Perry Feb 25 '12 at 1:44
    
@Perry Six one way, half-dozen the other. –  Borealid Feb 25 '12 at 1:45
    
is it possible that we can execute the code contained in environment variable on command line? –  Shahzad Feb 25 '12 at 1:57
    
By the way, if I do export such as export pqr="time ls" and if I specify this variable in some script then the code executes but if I place a for loop within this environment variable then shell yells at me and say for command not found. –  Shahzad Feb 25 '12 at 2:31
    
@Shazard, this answer implies you use SST as function. DATA=`STY()` (note left quotes - they get standard output of expression). To execute non-function variable (closer to your example) use eval $STY –  Basilevs Feb 25 '12 at 2:58
add comment

The problem has two sides:

  • storing complex expressions in variable
  • executing stored expression

To store expression, escape sequences and special quoting might be needed (that seems to be right in your example). Execution can be performed in two ways:

  • function call as in Borealid's answer: data=`STY()` - standard output of function is stored into variable
  • expression evaluation: data=eval $STY for variable definition given in your example
share|improve this answer
add comment

Short: use eval "$hello".

(This answer originally said: use eval $hello but another poster pointed out that eval "$hello" is safer.)

As shown below:

bash-2.05a$ export hello='for i in 0 1 2 3; do echo $i; done'

Simply saying $hello at the beginning of a line does not work - because for loops are processed before $variable expansion (phase oriented languages, I hate 'em):

bash-2.05a$ $hello
bash: for: command not found

But eval'ing works:

bash-2.05a$ eval $hello
0
1
2
3
bash-2.05a$ 

What you were (or might have been) doing wrong:

bash-2.05a$ export hello='for i in {0..4}; do echo $i; done'
bash-2.05a$ $hello
bash: for: command not found
bash-2.05a$ eval $hello
{0..4}
bash-2.05a$ for i in {0..4}; do echo $i; done
{0..4}
bash-2.05a$ 

I.e. at least in the version of bash I am using, {0..4} doesn't do what you thought it should.

http://www.cyberciti.biz/faq/bash-for-loop/ says that the {0..4} feature came in bash 3.0+.

Perhaps you, like me (at woprk, not home), are using an obsolete version of bash?

share|improve this answer
    
Don't use eval $hello, use eval "$hello". Without the double-quotes, some unwanted parsing is done, which can cause very weird bugs. See this answer for an example (in a rather different situation, but the same principles apply). –  Gordon Davisson Feb 25 '12 at 9:20
add comment

The reason why $hello doesn't run as you expected:

  • Expansion is performed on the command line after it has been split into tokens.
  • for...do...done is a Compound Command which is determined in tokenlize stage.
  • for is not a command.

So, you cannot do this:

$ "for" i in {0..4}; do echo $i; done
sh.exe": syntax error near unexpected token `do'

When bash split the command-line into tokens, It see "for" not for, so token do is unexpected.


In your case:

$ hello='for i in {0..4}; do echo $i; done'
$ $hello
sh.exe": for: command not found

Bash finds one token $hello, then variable-expansion&&word-spliting take place in order.
Actually, bash parses the result as a Simple Command:

  • command(for) takes rest as args(i,in,{0..4}, ;, do, ...)
  • for, do, ;, done, etc lost their special meanings.

read more for detail

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.