help-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Running commands as "$@"


From: Kerin Millar
Subject: Re: Running commands as "$@"
Date: Thu, 2 Feb 2023 15:18:31 +0000

On Thu, 2 Feb 2023 12:11:32 +0100
Cristian Zoicas <zoicas@medialab.sissa.it> wrote:

> Hello all
> 
> Let's assume the following script.
> 
> # ---- begin script runner.sh ----
> eval "$@"
> # ---- end script runner.sh ----
> 
> If we call this script with the following command line
> 
>      $ sh runner.sh ls -l
> 
> the 'ls -l' command will be executed.
> 
> Now, if a call the script with the commands
> 
>      $ sh runner.sh A=B
> 
> we get the following errors:
> 
>      runner.sh: 10: runner.sh: A=B: not found

That's not what happens in any conforming implementation of sh (see below).

> Why the shell does not treat the first string in "$@" ('A=B'
> in these cases) as the first possibile token of command (which
> is an assignemnt)?

Probably because the script that you presented isn't representative of the 
issue, in so far as you weren't using eval at the time.

> 
> In addition, the problem is NOT solved by using 'eval "$@"'.
> Apparently it works. For example the command
> 
>       $ sh runner.sh A=BCD
> 
>   works, but
> 
>       $ sh runner.sh A="B    CD"
> 
> gives an error. In this case the error (I think) comes
> from the way the expansion of "$@" is performed: eval has to evaluate the
> string "A=B   CD", so it treats A=B as an assignemnt and 'CD' as
> a command.

This is correct.

I think that your questions may be addressed overall by reading 
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_10_02.
 As concerns potential variable assignments that are the leading words of a 
simple command, the parser will only interpret them as such in the case that 
each of the applicable tokens contains an <equals-sign> and is not quoted in 
any way. Thus, the following examples do not work in the way that you might 
have imagined.

$ set -- A=B
$ "$1"
bash: A=B: command not found
$ 'A=B'
bash: A=B: command not found
$ \A=B
bash: A=B: command not found

Conversely, the following example works because the parameter expansion is 
performed prior to the resulting word(s) being injected into the tokeniser by 
eval. The observed token ends up being A=B, literally.

$ set -- 'A=B'
$ eval "$1"

-- 
Kerin Millar



reply via email to

[Prev in Thread] Current Thread [Next in Thread]