is there a way to have var. assignments on cmd line affect only a builtin cmd?

is there a way to have var. assignments on cmd line affect only a builtin cmd?

Post by Bob Mroczk » Tue, 22 Aug 2000 04:00:00



I'm using bash 2.03 and after reading the man page I understand
that bash will pass variable assignments on the command line,
before a command, to the environment of the command.

When I put a variable assignment before any builtin command the
assignment does not appear to be done.  For example,

IFS=- HARRY=hi echo ":$IFS:$HARRY:"
:
::

or this:
IFS='-' set -- 2000-08-21
echo $1

The above displays the entire date and not 2000.  Is there a way to
have these assignments work without resorting to a subshell?
I took a look at the 2.04 changes file and did not see anything
regarding this.

Bob

 
 
 

is there a way to have var. assignments on cmd line affect only a builtin cmd?

Post by Heiner Marx » Tue, 22 Aug 2000 04:00:00




Quote:>I'm using bash 2.03 and after reading the man page I understand
>that bash will pass variable assignments on the command line,
>before a command, to the environment of the command.

>When I put a variable assignment before any builtin command the
>assignment does not appear to be done.  For example,

>IFS=- HARRY=hi echo ":$IFS:$HARRY:"

At the time echo is executed the vars are already substituted.
Echo itself does not think about variables, anyhow.  So we need
some real program to be executed and find the vars (IFS and HARRY)
in its environment, or we have to get the shell to interpret them
_after_ they are assigned to.  Try:

IFS=- HARRY=hi eval 'echo ":$IFS:$HARRY:"'
:-:hi:

Quote:>or this:
>IFS='-' set -- 2000-08-21
>echo $1

This one is a bit harder.  AFAIK, command parsing itself does not
use IFS.  So we need a temporary variable:

x='2000-08-21'
IFS='-' eval 'set -- $x'
echo "$1"
2000

Cheers,
--


 
 
 

is there a way to have var. assignments on cmd line affect only a builtin cmd?

Post by Rene Wiesne » Wed, 23 Aug 2000 04:00:00


Heiner Marxen schrieb:

Quote:> At the time echo is executed the vars are already substituted.
> Echo itself does not think about variables, anyhow.  So we need
> some real program to be executed and find the vars (IFS and HARRY)
> in its environment, or we have to get the shell to interpret them
> _after_ they are assigned to.  Try:

> IFS=- HARRY=hi eval 'echo ":$IFS:$HARRY:"'
> :-:hi:

What about the use of /bin/echo? This is a real program, I think,
but it leads to the same result like the shell-builtin echo:

        HARRY=hi /bin/echo :$HARRY:
        ::

I've also tried:
        HARRY=hi printenv
and the (temporarily) variable is listed!

Can you explain me this behaviour?

#-------------------------------#
| R. Wiesner                    |

#-------------------------------#

 
 
 

is there a way to have var. assignments on cmd line affect only a builtin cmd?

Post by Dan Merc » Wed, 23 Aug 2000 04:00:00




> Heiner Marxen schrieb:

>> At the time echo is executed the vars are already substituted.
>> Echo itself does not think about variables, anyhow.  So we need
>> some real program to be executed and find the vars (IFS and HARRY)
>> in its environment, or we have to get the shell to interpret them
>> _after_ they are assigned to.  Try:

>> IFS=- HARRY=hi eval 'echo ":$IFS:$HARRY:"'
>> :-:hi:

> What about the use of /bin/echo? This is a real program, I think,
> but it leads to the same result like the shell-builtin echo:

>    HARRY=hi /bin/echo :$HARRY:

You are still not getting it.  The command line is parsed,  substituted
then executed.  So the shell looks into it's variables for HARRY.
HARRY is not set,  so the line becomes:

   HARRY=hi /bin/echo ::

next the shell executes the line by forking and placing HARRY=hi
into the forked process's environment.  

for IFS splitting in bash you need to save the IFS, reset it,
execute the command,  restore IFS:

   oIFS=$IFS
   IFS=:
   path=($PATH)
   IFS=$oIFS
   echo ${path[0]}

--
Dan Mercer

- Show quoted text -

>    ::

> I've also tried:
>    HARRY=hi printenv
> and the (temporarily) variable is listed!

> Can you explain me this behaviour?

> #-------------------------------#
>| R. Wiesner                    |

> #-------------------------------#

 
 
 

is there a way to have var. assignments on cmd line affect only a builtin cmd?

Post by Lisa Mroczk » Wed, 23 Aug 2000 04:00:00


Thank you for your reply.  I forgot about trying eval.



> >I'm using bash 2.03 and after reading the man page I understand
> >that bash will pass variable assignments on the command line,
> >before a command, to the environment of the command.

> >When I put a variable assignment before any builtin command the
> >assignment does not appear to be done.  For example,

> >IFS=- HARRY=hi echo ":$IFS:$HARRY:"

> At the time echo is executed the vars are already substituted.
> Echo itself does not think about variables, anyhow.  So we need
> some real program to be executed and find the vars (IFS and HARRY)
> in its environment, or we have to get the shell to interpret them
> _after_ they are assigned to.  Try:

> IFS=- HARRY=hi eval 'echo ":$IFS:$HARRY:"'
> :-:hi:

> >or this:
> >IFS='-' set -- 2000-08-21
> >echo $1

> This one is a bit harder.  AFAIK, command parsing itself does not
> use IFS.  So we need a temporary variable:

> x='2000-08-21'
> IFS='-' eval 'set -- $x'
> echo "$1"
> 2000

> Cheers,
> --


 
 
 

is there a way to have var. assignments on cmd line affect only a builtin cmd?

Post by Heiner Marx » Wed, 23 Aug 2000 04:00:00



Quote:>Heiner Marxen schrieb:

>> At the time echo is executed the vars are already substituted.
>> Echo itself does not think about variables, anyhow.  So we need
>> some real program to be executed and find the vars (IFS and HARRY)
>> in its environment, or we have to get the shell to interpret them
>> _after_ they are assigned to.  Try:

>> IFS=- HARRY=hi eval 'echo ":$IFS:$HARRY:"'
>> :-:hi:

>What about the use of /bin/echo? This is a real program, I think,
>but it leads to the same result like the shell-builtin echo:

>    HARRY=hi /bin/echo :$HARRY:
>    ::

Sure.  Please try to understand, how the shell works:
It will parse the above line in order to execute something.
First, there appears a var=value prefix for a command.
That is collected, nothing happens, yet.
Then there are found two tokens, first /bin/echo, then :$HARRY:,
which together are going to form a command.  The second contains
a variable invocation, which has to be substituted, before the command
is started.  This still uses the old HARRY value, which happens to be empty.
Now we have /bin/echo and ::.  Ok, no further substitutions asked for.
Now a new environment is built, containing "HARRY=hi", and a process is
spawned, executing /bin/echo with :: as its only argument.
Now, what should we expect /bin/echo to do?  Yes, output two colons and a NL.

Even it there would appear $HARRY in that echo argument, e.g. by
        HARRY=hi /bin/echo ':$HARRY:'
the echo command is not going to interpret the dollar special.
Thats just not the function of echo, it is a shell job.
/bin/echo does not look at environment variables.  We would get:
:$HARRY:

An entirely different matter would be:
        HARRY=hi
        /bin/echo :$HARRY:
Now, the first line is not a temporary environment modification for
a command, but rather an assignment command for the shell itself.
It will permanently (for the current subshell invokation) assign
hi to HARRY, regardless whether it is a plain shell variable or part
of the environment.  The old value of HARRY is gone.
Then, the echo command will be parsed, and the now current value of
HARRY will be used, which is "hi", will be used for substitution.
Therefore, this /bin/echo invocation will see :hi: and echo those
four characters, and a NL.
Whether or not HARRY=hi will be part of the environment of the
spawned process depends on whether HARRY has been exported, or is
just a plain shell variable.  Again, /bin/echo does not care.

BTW:    HARRY=hi ; /bin/echo :$HARRY:
would do the same, as the semicolon terminates the first part in the
same way as the newline in the above two-liner.

Quote:>I've also tried:
>    HARRY=hi printenv
>and the (temporarily) variable is listed!

>Can you explain me this behaviour?

Sure.
It _is_ the job of printenv to look into the environment (and print it).
HARRY=hi has been in the environment of /bin/echo, too, but that did
not matter.

I hope it is a bit clearer, now.
--

 
 
 

1. VAR=$(cmd) versus VAR=`cmd`

Consider the following:

  #!/bin/sh
  VAR=$(cmd1 | cmd2)

and

  #!/bin/sh
  VAR=`cmd1 | cmd2`

Apart from readability, is there any real difference between these two
scripts? When would the one method be used over the other and for what
reason?

Best regards,

Chris Morgan

Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.

2. Disk Druid doesn't see my whole HD

3. disk space cmd for cmd line entries

4. AIX 4.3.3: gdb and core files

5. capturing exit status for cmd when invoking 'xterm -e cmd'

6. How do I benchmark?

7. how to assign out=`cmd` w/out waiting for "cmd" to finish??

8. Routing with Redhat 6.2

9. ksh/bash: let cmd and test cmd interpret 08 (octal) differently

10. ksh/bash expr `cmd` vs $(cmd)

11. ksh/bash: let cmd and test cmd interpret 08 (octal) differently

12. backup CMD VS. savevg CMD

13. How can I do xterm -e 'cmd > cmd.log' ?